我在用着HwndSource
在非主窗口的 WPF 窗口中,为了挂钩窗口过程 (WndProc) 来接收一些消息:
WinSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
WinSource.AddHook(new HwndSourceHook(WndProc));
HwndSource
实施IDisposable
。 MSDN 不清楚我何时/应该处置它。的文档HwndSource.FromHwnd https://msdn.microsoft.com/en-us/library/system.windows.interop.hwndsource.fromhwnd%28v=vs.110%29.aspx解释上面的技术:
您可以使用此方法为不是显式互操作窗口的窗口返回 HwndSource。其程序是:
- 创建一个 WindowInteropHelper 实例(提供主 Window 作为构造函数参数)。
- 从该 WindowInteropHelper 实例获取 Handle 属性的值。
- 将该 HWND 值作为参数传递给 FromHwnd。
进而:
如果您随后想要向窗口添加常规 AddHook 消息处理,则此技术会很有用。然而,每当您创建 HwndSource 时,您也有责任销毁它。即使应用程序 HwndSource 的 Application 对象已释放,情况也是如此。
(重点是我的)
然而,在硬件源 https://msdn.microsoft.com/en-us/library/system.windows.interop.hwndsource%28v=vs.110%29.aspx类文档,我们看到:
对象生命周期
HwndSource 是常规公共语言运行时 (CLR) 对象,其生命周期由垃圾收集器管理。由于 HwndSource 代表非托管资源,因此 HwndSource 实现 IDisposable。 [...] 对于某些互操作场景,可能需要从互操作代码中显式调用 Dispose。
关于钩子:
实际的钩子由弱引用保存。因此,请确保管理钩子委托的生命周期。
我无法对此给出完整的答案,但根据最近的经验,我可以说你不应该处置HwndSource
对象太早 - 具体来说,直到它引用的窗口关闭为止。
我只是在调试一个这样完成的场景:
using(var source = HwndSource.FromHwnd(window.HWnd()))
{
source.AddHook(hook);
}
其结果是,在源被处理后,窗口立即变得不起作用(不再处理消息)。
简要浏览一下参考源FromHwnd()
,似乎它总是会为同一个窗口返回相同的对象。我认为这就是为什么你不能处置source
只是因为你自己的代码是用它完成的。显然HwndSource.Dispose()
不只是清理HWndSource
对象,而是一些非托管窗口本身。
注意到这一点后,现在我也看到了 HWndSource文档 https://learn.microsoft.com/en-us/dotnet/api/system.windows.interop.hwndsource says:
同步调用Dispose立即销毁Win32窗口
这似乎是我所观察到的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)