在 Win32 窗口中承载 WPF 的关键是使用 HwndSource 类。此类在 Win32 窗口中包装 WPF 内容,这样 WPF 内容可以作为子窗口并入到您的用户界面 (UI) 中。以下方法在一个应用程序中同时使用了 Win32 和 WPF。
-
将您的 WPF 内容(内容根元素)实现为托管类。通常,该类继承自可包含多个子元素和/或用作根元素的类之一,例如 DockPanel 或 Page。在后面的步骤中,该类称为 WPF 内容类,而该类的实例称为 WPF 内容对象。
-
使用 C++/CLI 实现 Win32 应用程序。如果您要从现有的非托管 C++ 应用程序开始操作,您通常可以通过将项目设置更改为包含 /clr 编译器标志来使该非托管应用程序可以调用托管代码(支持 /clr 编译所必需内容的完整范围没有在本主题中描述)。
-
将线程模型设置为单线程单元 (STA)。WPF 使用此线程模型。
-
在您的窗口过程中处理 WM_CREATE 通知。
-
在处理程序(或处理程序调用的函数)中,执行以下操作:
-
创建一个新 HwndSource 对象,并使用父窗口 HWND 作为其 parent 参数。
-
创建 WPF 内容类的一个实例。
-
将对 WPF 内容对象的引用分配给 HwndSource 对象的 RootVisual 属性。
-
HwndSource 对象的 Handle 属性包含窗口句柄 (HWND)。若要获得可在您的应用程序的非托管部分中使用的 HWND,请将 Handle.ToPointer() 强制转换为 HWND。
-
-
实现包含静态字段(该字段保留对您的 WPF 内容对象的引用)的托管类。此类允许您从您的 Win32 代码获得对 WPF 内容对象的引用,但是更为重要的是它可以防止您的 HwndSource 无意成为回收的垃圾。
-
通过将一个处理程序附加到一个或多个 WPF 内容对象事件来从 WPF 内容对象接收通知。
-
通过使用您在静态字段中存储的引用来设置属性、调用方法等,与 WPF 内容对象进行通信。
注意:
如果您单独生成一个程序集并引用它,则可以在 XAML 中,使用 WPF 内容类的默认分部类为步骤 1 实现该类的部分或全部定义。虽然您通常在将 XAML 编译为程序集时包括 Application 对象,但是您在互操作中并没有停止使用该 Application,您使用的是一个或多个由该应用程序引用的 XAML 文件的根类,并引用了其分部类。此过程的其余部分实际上类似于以上列出的过程。
详情见:MSDN的WPF与Win32互操作。