强制创建 WPF 窗口的本机 Win32 句柄
我需要访问一些 WPF 窗口的 Win32 窗口句柄,以便可以处理 Win32 激活消息。我知道我可以使用 PresentationSource.FromVisual
或 WindowInteropHelper
来获取 Win32 窗口句柄,但如果尚未创建 WPF 窗口,我就会遇到问题。
如果我使用 PresentationSource.FromVisual
并且尚未创建窗口,则返回的 PresentationSource
为 null。如果我使用 WindowInteropHelper 并且尚未创建窗口,则 Handle
属性为 IntPtr.Zero
(null)。
在尝试访问句柄之前,我尝试在窗口上调用 this.Show()
和 this.Hide()
。然后我可以获得句柄,但窗口会在屏幕上短暂闪烁(丑陋!)。
有谁知道强制创建 WPF 窗口的方法吗?在 Windows 窗体中,这就像访问 Form.Handle
属性一样简单。
编辑:我最终选择了克里斯·泰勒答案的变体。在这里,以防对其他人有帮助:
static void InitializeWindow(Window window)
{
// Get the current values of the properties we are going to change
double oldWidth = window.Width;
double oldHeight = window.Height;
WindowStyle oldWindowStyle = window.WindowStyle;
bool oldShowInTaskbar = window.ShowInTaskbar;
bool oldShowActivated = window.ShowActivated;
// Change the properties to make the window invisible
window.Width = 0;
window.Height = 0;
window.WindowStyle = WindowStyle.None;
window.ShowInTaskbar = false;
window.ShowActivated = false;
// Make WPF create the window's handle
window.Show();
window.Hide();
// Restore the old values
window.Width = oldWidth;
window.Height = oldHeight;
window.WindowStyle = oldWindowStyle;
window.ShowInTaskbar = oldShowInTaskbar;
window.ShowActivated = oldShowActivated;
}
// Use it like this:
InitializeWindow(myWpfWindow);
I need to access the Win32 window handles of some of my WPF windows so I can handle Win32 activation messages. I know I can use PresentationSource.FromVisual
or WindowInteropHelper
to get the Win32 window handle, but I am running into problems if the WPF window has not been created yet.
If I use PresentationSource.FromVisual
and the window has not been created, the returned PresentationSource
is null. If I use WindowInteropHelper
and the window has not been created, the Handle
property is IntPtr.Zero
(null).
I tried calling this.Show()
and this.Hide()
on the window before I tried to access the handle. I can then get the handle, but the window flashes momentarily on the screen (ugly!).
Does anyone know of a way to force a WPF window to be created? In Windows Forms this was as easy as accessing the Form.Handle
property.
Edit: I ended up going with a variant on Chris Taylor's answer. Here it is, in case it helps someone else:
static void InitializeWindow(Window window)
{
// Get the current values of the properties we are going to change
double oldWidth = window.Width;
double oldHeight = window.Height;
WindowStyle oldWindowStyle = window.WindowStyle;
bool oldShowInTaskbar = window.ShowInTaskbar;
bool oldShowActivated = window.ShowActivated;
// Change the properties to make the window invisible
window.Width = 0;
window.Height = 0;
window.WindowStyle = WindowStyle.None;
window.ShowInTaskbar = false;
window.ShowActivated = false;
// Make WPF create the window's handle
window.Show();
window.Hide();
// Restore the old values
window.Width = oldWidth;
window.Height = oldHeight;
window.WindowStyle = oldWindowStyle;
window.ShowInTaskbar = oldShowInTaskbar;
window.ShowActivated = oldShowActivated;
}
// Use it like this:
InitializeWindow(myWpfWindow);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用
WindowInteropHelper.EnsureHandle
,它正是您所需要的。Use
WindowInteropHelper.EnsureHandle
, it does exactly what you need.一种选择是将窗口状态设置为最小化,并且在显示窗口之前不显示在任务栏中。尝试这样的事情。
One option is to set window state to minimized and not to show in the taskbar before Showing the window. Try something like this.
如果 WindowInteropHelper 的句柄为 NULL,我正在寻找解决方案。希望这篇文章提供了一些如何解决该问题的附加信息。
一种解决方案是使用:
这仅适用于 .NET Framework 4。
目前我正在使用 .NET Framework 3.5,因此我需要另一种解决方案。然后我发现一个带有 WindowInteropHelper 扩展方法的论坛线程:
WindowInteropHelper.EnsureHandle() 不期望已经创建窗口。
I was looking for a solution if the WindowInteropHelper's handle is NULL. Hopefully this post gives some additional information how to solve it.
One solution is to use:
This works only with .NET Framework 4.
At the moment I am using .NET Framework 3.5 so I needed another solution. Then I found a forum thread with a WindowInteropHelper extension method:
The WindowInteropHelper.EnsureHandle() does not expect a window is already created.
我陷入了同样的问题,并选择了 J Pollack 的答案(因为它对我来说似乎更干净),但需要一些东西可以在 .NET 运行时 2.0 和 4.0 上运行。
但是当我这样做时,我最终得到了一个丑陋的 MissingMethodException,因为 .NET 运行时 4.0 中不再存在 SafeCreateWindow。为了使代码在两个运行时上都能工作,我决定捕获 MissingMethodException 并调用 .NET 4.0 运行时中的等效项,如下所示:
这使我可以使用 .NET 3.5 编译代码,但可以在以下系统上的 .NET 运行时 4.0 上运行它:仅安装了较高的运行时版本(即 Windows 8 及更高版本)。
I was stuck on this same issue and went with J Pollack's answer (because it seems cleaner to me), but needed something that would run both on the .NET runtime 2.0 and 4.0.
But when I did that I ended up with an ugly MissingMethodException because SafeCreateWindow does not exist in the .NET runtime 4.0 anymore. To make the code work on both runtimes I decided to catch the MissingMethodException and invoke the equivalent in the .NET 4.0 runtime instead like this:
This allowed me to compile the code with .NET 3.5 but run it on .NET runtime 4.0 on systems that only have the higher runtime version installed (namely Windows 8 and above).