接受器是一个微COM服务器,可以用ATL创建一个工程,添加接口函数,编译。保留其工程头文件“xxx.h”与接口ID即可。
本例中创建了名为ISinkServer的工程和名为ISink的接口,为添加接口方法test2(long lArg)。
2 服务器的创建
使用ATL创建名为RealServer的服务器(选择DLL),添加接口IReal(Apartment,Custom,Aggregation(Yes),Support Connection Points)。为接口添加方法test1(long lArg)。为_IRealEvents连接点添加回调方法test2(long lArg),并实现(Implement)其连接点。
在工程目录下加入guids.h,其中包含接收器IID_ISink。并在工程cpp的前端#include"guids.h"。
实现后的代码(RealServerCP.h)如下所示,修改完代码后便可在CReal中调用Fire_test2了。
#ifndef _REALSERVERCP_H_
#define _REALSERVERCP_H_
#include "..\SinkServer\SinkServer.h"
EXTERN_C const IID IID_ISink;
template
class CProxy_IRealEvents : public IConnectionPointImpl
{
public:
HRESULT Fire_test2(LONG lArg)
{
T* pT = (T*)this;
pT->Lock();
HRESULT ret;
IUnknown** pp = m_vec.begin();
while (pp < m_vec.end())
{
if (*pp != NULL)
{
ISink *pWzdSinks = reinterpret_cast(*pp);
ret = pWzdSinks->test2( lArg );
}
pp++;
}
pT->Unlock();
return ret;
}
};
#endif
3 客户端的创建
使用MFC建立对话框应用程序Client,在对话框头文件前端包含接收器接口工程头文件#include "SinkServer\SinkServer.h"。
并在消息定义宏下方添加:
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(SinkClass, ISink)
STDMETHOD_(HRESULT,test2)(long);
END_INTERFACE_PART(SinkClass)
在对话框cpp文件的消息定义宏下添加:
BEGIN_INTERFACE_MAP (CClientDlg, CClientDlg)
INTERFACE_PART (CClientDlg, IID_ISink, SinkClass)
END_INTERFACE_MAP ()
完成接收器的几个基本函数与自定义函数:
ULONG FAR EXPORT CClientDlg::XSinkClass::AddRef()
{
METHOD_PROLOGUE(CClientDlg, SinkClass);
return pThis->ExternalAddRef();//pThis accesses enclosing class's this pointer
}
ULONG FAR EXPORT CClientDlg::XSinkClass::Release()
{
METHOD_PROLOGUE(CClientDlg, SinkClass);
return pThis->ExternalRelease();
}
HRESULT FAR EXPORT CClientDlg::XSinkClass::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CClientDlg, SinkClass);
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
HRESULT __stdcall CClientDlg::XSinkClass::test2(long lArg)
{
METHOD_PROLOGUE(CClientDlg, SinkClass);
CString str;
str.Format("%d",lArg);
AfxMessageBox(str);
return S_OK;
}
在对话框cpp文件的前端加入,其中guids.h为包含接收器IID头文件,IID_IReal和CLSID_Real从服务器RealServer获取:
#include "guids.h"
#include "RealServer/RealServer.h"
#include
const IID IID_IReal = {0xA8CA226A,0x69B1,0x4D10,{0x9A,0x25,0xD0,0x71,0x96,0x0B,0xD8,0x85}};
const CLSID CLSID_Real = {0xEA9E614F,0x5EBE,0x41ED,{0x9B,0x96,0xF7,0x6D,0x37,0xB1,0xEB,0x29}};
接下来便可以在程序中进行接口调用了。
void CClientDlg::OnOK()
{
// TODO: Add extra validation here
HRESULT hr;
IReal *IMyReal = NULL;
hr = CoInitialize(0);
if (SUCCEEDED(hr))
{
//以下两段代码二选一
/***************************/
/*hr = CoCreateInstance(CLSID_Real,
NULL,
CLSCTX_INPROC_SERVER,
IID_IReal,
(void**)&IMyReal);*/
/***************************/
IClassFactory* pIFactory = NULL;
hr = CoGetClassObject(CLSID_Real,
CLSCTX_INPROC_SERVER,
NULL,
IID_IClassFactory,
(void**)&pIFactory);
if (SUCCEEDED(hr))
{
// create the component.
hr = pIFactory->CreateInstance(NULL, IID_IReal, (void**)&IMyReal);
pIFactory->Release();
}
/****************************/
}
ISink *IMySink = NULL;
hr = m_xSinkClass.QueryInterface(IID_ISink,(void**)&IMySink);
m_xSinkClass.Release();
DWORD dwConnectID;
hr = AfxConnectionAdvise(
IMyReal, // the real server
IID_ISink, // our sink's IID
IMySink, // our sink's pointer
FALSE, // TRUE == increment our sink object's ref count
&dwConnectID); // identifier for AfxConnectionUnadvise()
IMyReal->test1(1);
AfxConnectionUnadvise(
IMyReal, // the real server
IID_ISink, // our sink's IID
IMySink, // our sink's pointer
FALSE, // TRUE == decrement our sink object's ref count
dwConnectID); // identifier from AfxConnectionAdvise()
CoUninitialize();
}