问题描述
我正在编写一个进程外COM服务器(* .exe),它应该使用资源模板显示一个对话框。资源包含在服务器的exe文件中。我正在使用VC ++ 2010,该项目具有MFC支持并且大量使用MFC类。代码归结为:
Hi,
I am writing an out-of-process COM server (*.exe) which should display a dialog using a resource template. The resource is contained in the server's exe file. I am using VC++ 2010, and the project has MFC support and makes heavy use of MFC classes. The code boils down to this:
STDMETHODIMP CMyComServer::MyMethod()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
AfxSetResourceHandle(_AtlBaseModule.GetResourceInstance()); // see text below
CWinApp *pApp = AfxGetApp(); // see text below
CDialog objDlg(IDD_MY_DIALOG, NULL);
objDlg.DoModal();
return S_OK;
}
会发生什么:当 CWnd :: CreateDlgIndirect 调用
因为 AfxGetApp() - > IsKindOf(RUNTIME_CLASS(COleControlModule))
因为 AfxGetApp()
返回一个NULL指针。
为了验证这一点,我插入了行 CWinApp * pApp = AfxGetApp();
它为pApp分配NULL。
当我删除对 AfxSetResourceHandle
的调用时,断言在<$中触发c $ c> AfxGetResourceHandle() afxCurrentResourceHandle
为NULL。
我的项目似乎没有CWinApp派生类。 VC ++ 2010不提供COM out-proc服务器向导,因此我克隆了一个没有GUI的out-proc服务器项目。我是否必须添加应用程序对象?如果是这样,怎么样?
谢谢...... Hans
What happens is this: The call to DoModal asserts when CWnd::CreateDlgIndirect
calls AfxGetApp()->IsKindOf(RUNTIME_CLASS(COleControlModule))
because AfxGetApp()
returns a NULL pointer.
To verify this, I inserted the line CWinApp *pApp = AfxGetApp();
which assigns NULL to pApp.
When I remove the call to AfxSetResourceHandle
, the assertion is triggered in AfxGetResourceHandle()
because afxCurrentResourceHandle
is NULL.
My project seems not to have a CWinApp-derived class. VC++ 2010 does not provide a COM out-proc server wizard, so I cloned an out-proc server project which has no GUI. Do I have to add an application object? If so, how?
Thanks... Hans
推荐答案
STDMETHODIMP CMyComServer::MyInterfaceFunction(...)
{
// Don't call AFX_MANAGE_STATE!
AfxSetResourceHandle(_AtlBaseModule.GetResourceInstance());
CMyGuiThread *pThread = dynamic_cast<cmyguithread*>AfxBeginThread(RUNTIME_CLASS(CMyGuiThread)));
}
GUI线程在其InitInstance函数中创建对话框。
The GUI thread, in its InitInstance function, creates the dialog.
/*virtual*/ BOOL CMyGuiThread::InitInstance()
{
CMyDlg *pWnd = new CMyDlg;
BOOL bRes = pWnd->Create();
if (bRes)
m_pWnd = pWnd;
else
delete pWnd;
return bRes;
}
CMyGuiThread :: m_pWnd成员存储一个指向CMyDlg对象的指针,这样你就可以销毁对话框不再需要。 (请注意,对话框可能会因为IDOK或IDCANCEL控件点击而自行销毁,并且响应右上角的X图标点击;在这种情况下,m_pWnd指向无效的内存;您必须覆盖CMyDlg :: OnCancel和OnOk以防止这种情况。)
对话框在其Create函数中调用其中一个继承的重载。
The CMyGuiThread::m_pWnd member stores a pointer to the CMyDlg object so that you can destroy the dialog when it is no longer required. (Be aware that a dialog can destroy itself in response to IDOK or IDCANCEL control clicks and inresponse to a click on the X icon in the upper right corner; in that case, m_pWnd points to invalid memory; you must overwrite CMyDlg::OnCancel and OnOk to prevent this.)
The dialog, in its Create function, calls one of the inherited overloads.
/*virtual*/ BOOL CMyDlg::Create()
{
return __super::Create(IDD, NULL);
}
也许重要的是不要使用通常放在每个方法开头的AFX_MANAGE_STATE宏通过COM接口调用。
Maybe the important thing is not to use the AFX_MANAGE_STATE macro which you usually put at the beginning of each method that is called over the COM interface.
这篇关于从COM服务器中的资源创建对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!