我试图创建一个ActiveX控件,其中包含一个System.Windows.Forms.Integration.ElementHost控件来托管控件中的WPF内容。
我能够使用MFC创建ActiveX控件,我还可以在其中加载MFC CDialog。但是,只要我尝试创建托管控件,它就会在
处出现AccessViolationException而崩溃return CreateControl(info,dwStyle,&pt,&size,pParentWnd,nID);
这在afxwinforms.inl:122。
我的MainDialog.cpp文件如下所示:
// MainDialog.cpp : implementation file
//
#include "stdafx.h"
#include "MFCAX.h"
#include "MainDialog.h"
#include "afxdialogex.h"
// CMainDialog dialog
IMPLEMENT_DYNAMIC(CMainDialog, CDialog)
CMainDialog::CMainDialog(CWnd* pParent /*=NULL*/)
: CDialog(CMainDialog::IDD, pParent)
{
}
CMainDialog::~CMainDialog()
{
}
void CMainDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//DDX_ManagedControl(pDX, IDC_BUTTON1, m_elementHost);
}
BOOL CMainDialog::OnInitDialog()
{
CDialog::OnInitDialog();
AFX_MANAGE_STATE(AfxGetStaticModuleState());
System::Windows::Forms::MessageBox::Show(gcnew System::String("init"));
return m_elementHost.CreateManagedControl(WS_CHILD | WS_VISIBLE, IDC_BUTTON1, this);
}
BEGIN_MESSAGE_MAP(CMainDialog, CDialog)
END_MESSAGE_MAP()
// CMainDialog message handlers
显示消息框,但随后会出现上述崩溃。
我觉得只有一小部分缺失,但我真的不知道在哪里搜索。任何帮助表示赞赏。
答案 0 :(得分:0)
我终于明白了,所以我会快速概述一下这里有类似问题的人在做什么:
首先:不要在WinForms ElementHost路由中使用WPF,它比这更容易!
要加载WPF控件并将其显示在ActiveX控件上,请使用以下方法:
HWND CMFCAXCtrl::GetUserControl1Hwnd(HWND parent, int x, int y, int width, int height)
{
System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters("MFCWPFApp");
sourceParams->PositionX = x;
sourceParams->PositionY = y;
sourceParams->Height = height;
sourceParams->Width = width;
sourceParams->ParentWindow = System::IntPtr(parent);
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD;
m_hwndSource = gcnew System::Windows::Interop::HwndSource(*sourceParams);
EventReceiver^ recv = gcnew EventReceiver(this);
m_wpfUC = gcnew WpfExample::TestControl();
m_wpfUC->Clicked += gcnew System::EventHandler(recv, &EventReceiver::Handler);
m_hwndSource->RootVisual = m_wpfUC;
return (HWND) m_hwndSource->Handle.ToPointer();
}
你必须设置一个HwndSource来绘制WPF控件。你也可以连接事件处理程序等来处理C ++中的WPF事件(参见Clicked事件处理程序)。
相应的成员定义如下:
gcroot<System::Windows::Interop::HwndSource^> m_hwndSource;
gcroot<WpfExample::TestControl^> m_wpfUC;
HWND m_hwndWPF;
现在出现了棘手的部分:在加载像这样的程序集时似乎存在问题,找不到任何未安装在GAC中的程序集。因此,您必须连接自己的装配解析器。在那里你必须确保一个程序集只加载一次,否则你会得到奇怪的错误和异常。快速而肮脏的实现可能如下所示:
ref class Resolved {
public:
// just needed to store the assembly that was loaded.
static System::Reflection::Assembly^ assembly;
};
System::Reflection::Assembly^ ResolveHandler(System::Object^ Sender, System::ResolveEventArgs^ args)
{
return Resolved::assembly;
}
并在控件的OnCreate方法中:
Resolved::assembly = System::Reflection::Assembly::LoadFile(gcnew System::String("Path:\\To\\My\\assembly\\WpfExample.dll"));
System::AppDomain::CurrentDomain->AssemblyResolve += gcnew System::ResolveEventHandler(ResolveHandler);
// To create the main dialog
m_hwndWPF = GetUserControl1Hwnd(this->GetSafeHwnd(), 0, 0, 500, 500);
现在你已经完成所有设置,你应该能够在任何支持ActiveX的遗留项目中使用WPF。