在WPF中,PresentationSource.FromVisual(this)返回了一个空值

10

我正在使用以下代码:

protected override void OnSourceInitialized(EventArgs e)
{
...
....
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
...
...
}

在某些系统中,“source”值变成了null,我无法找出原因...
3个回答

11

我认为在尝试分配Hwnd之前,您可能需要等待UI被呈现。请将其放置在Window.Loaded的事件处理程序中。

这种情况以前曾经发生过,当时我在代码后台的构造函数中调用InitializeComponent()之后进行了Hwnd分配。它总是返回null,当我跟踪并看到UI尚未出现时,这可能是有道理的。我将其弹入_Loaded处理程序中,然后突然之间,UI在达到该行之前会被渲染,而“this”也停止为空。


我在 UserControl_Loaded 中进行了这样的操作,它正常运行良好,但在一些奇怪的情况下(应用在远程桌面系统上运行,并且长时间不触摸),它会返回 null。 - Zoli
我把它放在UserControl_Loaded里,它正常运作,但是在某些奇怪的情况下(应用程序在远程桌面系统上运行,并且你没有触摸它运行几个小时),它会返回null。 - Zoli

8

从 .Net 4.0 开始,您可以在不必先显示窗口的情况下访问 HwndSource

var helper = new WindowInteropHelper(this);
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());

在调用WindowInteropHelper.EnsureHandle之后,我仍然从PresentationSource.FromVisual获取到null。看起来我实际上必须显示窗口。FromVisual可能需要其他内部事物进行惰性创建,超出了句柄的范畴。 - Drew Noakes
为什么不使用 HwndSource.FromHwnd 呢? - Jan Gassen
1
因为我需要演示源来访问组合目标,以访问矩阵并访问DPI值。 - Drew Noakes
1
你可以尝试使用 new HwndTarget(helper.EnsureHandle()) 来访问合成目标并从那里继续吗? - Jan Gassen
有趣的想法。我已经实施了一个解决方法并继续前进,但是我偶尔会遇到这个问题,所以下次会尝试一下。非常感谢。 - Drew Noakes

5

WumpasTamer的回答是正确的。我只想为其他正在寻找“即插即用”解决方案的人添加一个快速的代码示例。如果您已经在使用WPF,那么window是不必要的,但如果您正在使用Winforms并且想要使用PresentationSource,则需要使用此选项。

void Main()
{
    var window = new Window
    {
        Width = 0,
        Height = 0,
        WindowStyle = WindowStyle.None,
        ShowInTaskbar = false,
        ShowActivated = false
    };
    window.Loaded += a_Loaded;
    window.Show();
}

void a_Loaded(object sender, EventArgs e)
{
    var s = (Window) sender;
    var source = PresentationSource.FromVisual(s);
    //...
    s.Close();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接