如何在MFC应用程序中托管WPF内容?

时间:2009-05-06 14:43:20

标签: wpf mfc wpf-controls

我将在这里回答我自己的问题,因为我花了几个小时将它拼凑在一起并希望分享我发现的东西,希望我能拯救别人挖掘。

有一个MSDN Walkthrough可以帮助你完成大部分工作,但我在其他地方找到了几个关键部分。例如,演练告诉您将行[System :: STAThreadAttribute]放在_tWinMain()定义之前,但如果您正在实现标准MFC应用程序,那么您的源代码中没有_tWinMain()。

如果此处的任何内容不清楚,请随时提出问题,我会编辑答案以使事情更加清晰。

1 个答案:

答案 0 :(得分:23)

步骤1:配置MFC应用程序以使用CLR支持进行编译

实现本机C ++和托管.NET代码之间的互操作性的最佳方法是将应用程序编译为托管C ++而不是本机C ++。这是通过转到项目的配置属性来完成的。在General下,有一个选项“Common Language Runtime support”。将其设置为“Common Language Runtime Support / clr”。

第2步:将WPF程序集添加到项目中

在解决方案资源管理器中右键单击项目,然后选择“参考”。单击“添加新参考”。在.NET选项卡下,添加WindowsBase,PresentationCore,PresentationFramework和System。确保在添加任何引用后重新构建所有引用,以便它们被拾取。

步骤3:在MFC应用程序上设置STAThreadAttribute

WPF要求在主UI线程上设置STAThreadAttribute。通过转到项目的“配置属性”来设置此项。在Linker-> Advanced下,有一个名为“CLR Thread Attribute”的选项。将其设置为“STA线程属性”。

步骤4:创建HwndSource实例以包装WPF组件

System :: Windows :: Interop :: HwndSource是一个.NET类,用于处理MFC和.NET组件之间的交互。使用以下语法创建一个:

System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew     System::Windows::Interop::HwndSourceParameters("MyWindowName");
sourceParams->PositionX = x;
sourceParams->PositionY = y;
sourceParams->ParentWindow = System::IntPtr(hWndParent);
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD;

System::Windows::Interop::HwndSource^ source = gcnew System::Windows::Interop::HwndSource(*sourceParams);
source->SizeToContent = System::Windows::SizeToContent::WidthAndHeight;

将HWND成员变量添加到对话框类中,然后像这样分配: m_hWnd =(HWND)source-> Handle.ToPointer();

源对象和关联的WPF内容将保持存在,直到您调用:: DestroyWindow(m_hWnd)。

步骤5:将WPF控件添加到HwndSource包装器

System::Windows::Controls::WebBrowser^ browser = gcnew System::Windows::Controls::WebBrowser();

browser->Height = height;
browser->Width = width;
source->RootVisual = browser;

第6步:保留对WPF对象的引用

由于浏览器变量在退出创建函数后将超出范围,我们需要以某种方式保存对它的引用。托管对象不能是非托管对象的成员,但您可以使用名为gcroot的包装器模板来完成工作。

将成员变量添加到对话框类:

#include <vcclr.h>
gcroot<System::Windows::Controls::WebBrowser^> m_webBrowser;

然后将以下行添加到步骤5中的代码中:

m_webBrowser = browser;

现在我们可以通过m_webBrowser访问WPF组件上的属性和方法。