对MFC创建COM组件和实现COM连接点的小结
1.如果要在普通工程中使用COM组件,包含以下ATL头文件:
#include <afxdisp.h>
#include <atlbase.h>
//You may derive a class from CComModule and use it if you want to override
//something, but do not change the name of _Module
extern CComModule _Module;
#include <atlcom.h>
注意:头文件顺序不能改变。(不太清楚原因,但是只要头文件顺序改变,complile错误。)
2.从一个连接点机制的实例看开来:
(1)按照COM规范来写自定义组件:
一个在client端实现的普通双接口的组件,继承服务器端定义的事件接口如下:
class CMyEvent :
public IDispatchImpl<_IConnectionObjEvents, &DIID__IConnectionObjEvents, &LIBID_COM_CPLib>,
public CComObjectRoot
{
public:
CMyEvent()
{
}
BEGIN_COM_MAP(CMyEvent)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(_IConnectionObjEvents)
END_COM_MAP()
// IMyEvent methods
STDMETHODIMP CMyEvent::Click()
{
AfxMessageBox("Get message from IConnetionObj");
return S_OK;
}
};
其中Click()是自定义事件。
(2)客户端工程中按步骤和COM组件建立连接。(思路如此,但我在调试时会弹出调对话框,跟踪发现连接已建立...暂时没有找到原因,如果哪位知道原因请告诉我。)
HRESULT hr = CoInitialize(NULL);
if(FAILED(hr))
{
AfxMessageBox("Coinitialize() failed!");
return 0 ;
}
IUnknown *pIUnknown = NULL;
hr = CoCreateInstance( CLSID_ConnectionObj , NULL ,
CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pIUnknown) ;
if( FAILED(hr) )
{
AfxMessageBox("Con't get IUnknown interface!");
return 0 ;
}
IConnectionObj *pIConnectionObj = NULL;
if( pIUnknown!= NULL)
{
hr = pIUnknown->QueryInterface(IID_IConnectionObj, (void **)&pIConnectionObj);
if(FAILED(hr))
{
AfxMessageBox("Can't get IConnectionObj interface!") ;
return 0 ;
}
}
IConnectionPointContainer *pIConnPtCont = NULL;
if(pIConnectionObj!=NULL)
{
hr=pIConnectionObj->QueryInterface(IID_IConnectionPointContainer,(LPVOID*)&pIConnPtCont) ;
if(FAILED(hr))
{
AfxMessageBox("Can't get IConnectionPointContainer interface!");
return 0;
}
}
IConnectionPoint *pIConnPt = NULL;
if(pIConnPtCont!=NULL)
{
hr = pIConnPtCont->FindConnectionPoint (DIID__IConnectionObjEvents, &pIConnPt);
if(FAILED(hr))
{
AfxMessageBox("Can't get IConnectionPoint interface!");
return 0;
}
}
printf("Get IConnectionPoint interface!\n");
CComObject<CMyEvent> *pEvent = NULL;
CComObject<CMyEvent>::CreateInstance(&pEvent);
ASSERT(pEvent);
// give this pointer to the server
pIUnknown = NULL;
hr = pEvent->QueryInterface(__uuidof(IUnknown), (void **) &pIUnknown);
if (FAILED(hr))
{
AfxMessageBox("pEvent->QueryInterface() fail!");
return 0;
}
hr = pIConnPt->Advise(pIUnknown, &dwMyEvt);
if (FAILED(hr))
{
AfxMessageBox("pIConnPt->Advise() faile!");
return 0;
}
// Do some work
pIConnectionObj->DoClick(); //DoClick()在server端定义,在client端实现
hr = pIConnPt->Unadvise( dwMyEvt );
if (FAILED(hr))
{
AfxMessageBox("pIConnPt->Unadvise() faile");
return 0;
}
pEvent->Release();
pIConnPt->Release();
pIConnPtCont->Release();
pIConnectionObj->Release();
pIUnknown->Release();
CoUninitialize();
}