强制初始化HwndHost

Dan*_*ose 5 .net wpf hwndhost wpf-4.0

在我的WPF应用程序中,我使用HwndHost托管Win32内容.但是,创建HwndHost不会创建本机窗口.相反,这是在重写的BuildWindowCore()方法中完成的,该方法稍后由WPF调用.

我的托管内容需要本机窗口的窗口句柄以进行自己的初始化.不幸的是,我无法强制创建窗口(即让WPF调用BuildWindowCore),所以我有第二个线程轮询HwndHost,直到它被初始化.

在.NET 4.0/WPF 4.0中,WindowInteropHelper.EnsureHandle()添加了一种新方法.我希望这可以解决这种情况,但它只适用于Window,而不适用于HwndHost(它不是从Window派生的).你有建议我可以做什么吗?

编辑:

我忘了为可能的解决方案添加更多约束:

  1. HwndHost放置在一个控件中,根据用户设置,该控件可以是应用程序主窗口的子窗口,也可以放在新窗口中(通过第三方停靠管理器).这意味着在创建窗口期间,我不确定父窗口(以及它的hWnd)将是什么.
  2. 虽然本机代码在初始化期间需要hWnd,但窗口仅在用户请求显示时显示(即,它首先是不可见的).如果可能的话,应该避免显示窗口,只是立即再次隐藏它.

Dan*_*ose 3

似乎没有完美的解决方案。与提出问题时相比,我稍微改变了我的方法:

在我的 HwndHost 派生类的构造函数中,我将(可能的)父 hWnd 作为参数之一。CreateWindow()然后,我使用本机方法,使用给定的父 hWnd创建本机窗口。我将创建的 hWnd 存储在一个单独的属性中,我在任何地方都使用该属性,而不是 HwndHost 的 Handle 属性。这样,我就不需要显示窗口(这解决了约束#2)。

在重写的BuildWindowCore()方法中,我将给定的父 hWnd 与构造函数中给定的 hWnd 进行比较。如果它们不同,我将使用本机SetParent()方法重新设置我的托管窗口的父级(这解决了约束 #1)。请注意,这依赖于没有人存储父 hWnd!

在代码中,相关部分(检查省略):

public class Win32Window : HwndHost
{
    public Win32Window(IntPtr parentHwnd)
    {
        this.ParentHwnd = parentHwnd;
        this.Win32Handle = NativeMethods.CreateWindowEx( /* parameters omitted*/ );
    }

    public IntPtr Win32Handle { get; private set; }
    private IntPtr ParentHwnd { get; set; }

    protected override HandleRef BuildWindowCore(HandleRef hwndParent)
    {
        if (hwndParent.Handle != this.ParentHwnd)
        {
            NativeMethods.SetParent(this.Win32Handle, hwndParent.Handle);
        }

        return new HandleRef(this, this.Win32Handle);
    }
}
Run Code Online (Sandbox Code Playgroud)