在我的WPF应用程序中,我使用HwndHost托管Win32内容。但是,创建HwndHost不会创建本机窗口。相反,这是在重写的BuildWindowCore()
方法中完成的,该方法稍后由WPF调用。
我的托管内容需要本机窗口的窗口句柄才能进行自己的初始化。不幸的是,我无法强制创建窗口(即让WPF调用BuildWindowCore),所以我有第二个线程轮询HwndHost,直到它被初始化。
在.NET 4.0 / WPF 4.0中,添加了一个新方法WindowInteropHelper.EnsureHandle()
。我希望这可以解决这种情况,但它只适用于Window,而不适用于HwndHost(它不是从Window派生的)。你有建议我可以做什么吗?
编辑:
我忘了为可能的解决方案添加更多约束:
答案 0 :(得分:3)
似乎没有完美的解决方案。与被问到的问题时间相比,我略微改变了我的方法:
在我的HwndHost派生类的构造函数中,我将(可能的)父hWnd作为参数之一。然后,我使用给定的父hWnd使用本机CreateWindow()
方法创建本机窗口。我将创建的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);
}
}
答案 1 :(得分:1)
我有类似的情况,我通过以下方式解决了这个问题:
1)创建一个HwndHost派生类,该类将Rect作为构造函数参数(稍后在BuildWindowCore中使用):
public class MyHwndHost : HwndHost
{
public MyHwndHost(Rect boundingBox)
{
BoundingBox = boundingBox;
}
}
2)使用子Border元素创建一个WPF窗口:
<Window Loaded="Window_Loaded">
<Border Name="HostElement" />
</Window>
3)创建HwndHost实例并将其添加到Window_Loaded处理程序中的窗口:
void Window_Loaded(object sender, RoutedEventArgs e)
{
MyHwndHost host = new MyHwndHost(LayoutInformation.GetLayoutSlot(HostElement));
HostElement.Child = host;
}
4)同样在Window_Loaded处理程序中,通过P / Invoke或C ++ / CLI将HWND传递给本机类的初始化。我将我的本机类设置为使用该HWND作为其父级,并且它作为子级创建自己的HWND。
答案 2 :(得分:0)
有点晚了,但你试过在主机控件上调用UpdateLayout()
吗?这对我有用
答案 3 :(得分:0)
我将事件OnHandleCreated
添加到我的HwndHost
- 继承的类,其中包含句柄IntPtr。此事件在BuildWindowCore()
内调用。
所以归结为:
public class Win32WindowHost : HwndHost { ... }
var host = new Win32WindowHost();
host.OnHandleCreated += ( sender, e ) =>
{
var handle = e.Handle;
// Do stuff.
};
努力享受。