In my WPF application, I host Win32 content using HwndHost. However, creating a HwndHost does not create the native window. Rather, this is done in the overridden BuildWindowCore()
method which is called sometime later by WPF.
My hosted content needs the window handle of the native window for its own initialization. Unfortunately, there is no way I can force the creation of the window (i.e. having WPF call the BuildWindowCore), so I have a second thread which polls the HwndHost until it has been initialized.
In .NET 4.0 / WPF 4.0, a new method WindowInteropHelper.EnsureHandle()
was added. I had hoped this would resolve the situation, but it only works for a Window, not a HwndHost (which doesn't derive from Window). Do you have a suggestion what I could do instead?
EDIT:
I forgot to add some more constraints for a possible solution:
There seems to be no perfect solution. I changed my approach slightly compared to the time of the question being asked:
In the constructor of my HwndHost-derived class I have the (possible) parent hWnd as one of the parameters. I then create the native window using the native CreateWindow()
method, using the given parent hWnd. I store the created hWnd in a separate property, which I use everywhere instead of the HwndHost's Handle property. That way, I don't need to show the window (this solves constraint #2).
In the overridden BuildWindowCore()
method, I compare the given parent hWnd with the one I was given in the constructor. If they are different, I reparent my hosted window using the native SetParent()
method (this solves constraint #1). Note that this relies on nobody storing the parent hWnd!
In code, the relevant parts (checks omitted):
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);
}
}