怎么接收COM组件事件(100分奉上)
如何接收COM组件事件(100分奉上)
一个硬件厂家提供的设备,现在要读取这个设备的事件。厂家做了一个COM组件,我要在我的DLL中访问这个组件。
现在主要是接收事件这块出问题了。
我在VC6.0、WindowsXP下开发。
其实,本来厂家是提供了DEMO程序的,如果照着那个DEMO做很容易的。
但因为我不能使用MFC的东西(主要是为了平台兼容),所以很费劲。
接收事件我用的是网上提供的CSink类的方法,就是继承IDispEventImpl而自己写的类,在这个类中接收事件。
类如下:
static _ATL_FUNC_INFO info2 =
{
CC_STDCALL, // Calling convention.
VT_HRESULT, // Return type.
2, // Number of arguments.
{ VT_BSTR, VT_I2 } // Argument types.
};
class CSvrEvent :
public CRefCount, public IDispEventImpl<IDC_TMPE_ID,CSvrEvent,
&__uuidof(IServerEvents), // Source interface GUID.
&LIBID_CSSAppServer, // typelib ID containing source interface.
1, // Major version # of LIBID_COMOBJLib. 0> // Minor version # of LIBID_COMOBJLib.
{
public:
CSvrEvent();
CSvrEvent(IServer *pIApplet);
~CSvrEvent(void);
BEGIN_SINK_MAP(CSvrEvent)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000001, ControllerDetected, &info2)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000002, ControllerOnline, &info2)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000003, ControllerOffline, &info2)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000004, DoorStatusChanged, &info4)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000005, PointStatusChanged, &info4_1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000006, ControllerSearchEnd, &info1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000007, NetNodeOnline, &info1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000008, NetNodeOffline, &info1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000009, UncommonDoorEvent, &info4_2)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x0000000a, HistoryEvent, &info1_1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x0000000b, UserAreaChanged, &info4_3)
END_SINK_MAP()
// IUnknown methods
ULONG STDMETHODCALLTYPE AddRef(void);
ULONG STDMETHODCALLTYPE Release(void);
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void * *ppvObj);
// 组件发出的事件函数
STDMETHODCALLTYPE ControllerDetected(_bstr_t NodeIName, short CtrlAddr);
STDMETHODCALLTYPE ControllerOnline(_bstr_t NodeName, short CtrlAddr);
STDMETHODCALLTYPE ControllerOffline(_bstr_t NodeName, short CtrlAddr);
STDMETHODCALLTYPE DoorStatusChanged(_bstr_t NodeName, short CtrlAddr, long DoorAddr, long Status);
STDMETHODCALLTYPE PointStatusChanged(_bstr_t NodeName, short CtrlAddr, short PointAddr, long Status);
STDMETHODCALLTYPE ControllerSearchEnd(_bstr_t NodeName);
STDMETHODCALLTYPE NetNodeOnline(_bstr_t NodeName);
STDMETHODCALLTYPE NetNodeOffline(_bstr_t NodeName);
STDMETHODCALLTYPE UncommonDoorEvent(_bstr_t NodeName,WORD EventType,WORD CtrlAddr,WORD DoorAddr);
STDMETHODCALLTYPE HistoryEvent(long Events);
STDMETHODCALLTYPE UserAreaChanged (_bstr_t NodeName, long ZoneNo, long CardNo, short Area);
};
下面是在初始化时引用这个事件类的代码:
COSERVERINFO ServerInfo;
MULTI_QI Results;
ServerInfo.dwReserved1 = 0;
ServerInfo.dwReserved2 = 0;
ServerInfo.pAuthInfo =NULL;
ServerInfo.pwszName = L"192.168.0.106"; //远程服务器机器名
Results.pIID = &IID_IServer;
Results.pItf = NULL;
HRESULT hr;
hr = CoCreateInstanceEx(CLSID_Server,NULL,
CLSCTX_REMOTE_SERVER,&ServerInfo,1,&Results);
if(FAILED(hr))
{
MessageBox(NULL, "Connect to Server failed","Error",MB_OK | MB_ICONSTOP);
return FALSE;
}
Results.pItf->QueryInterface(&m_pServer);
CComPtr<IConnectionPointContainer> pCPC;
一个硬件厂家提供的设备,现在要读取这个设备的事件。厂家做了一个COM组件,我要在我的DLL中访问这个组件。
现在主要是接收事件这块出问题了。
我在VC6.0、WindowsXP下开发。
其实,本来厂家是提供了DEMO程序的,如果照着那个DEMO做很容易的。
但因为我不能使用MFC的东西(主要是为了平台兼容),所以很费劲。
接收事件我用的是网上提供的CSink类的方法,就是继承IDispEventImpl而自己写的类,在这个类中接收事件。
类如下:
static _ATL_FUNC_INFO info2 =
{
CC_STDCALL, // Calling convention.
VT_HRESULT, // Return type.
2, // Number of arguments.
{ VT_BSTR, VT_I2 } // Argument types.
};
class CSvrEvent :
public CRefCount, public IDispEventImpl<IDC_TMPE_ID,CSvrEvent,
&__uuidof(IServerEvents), // Source interface GUID.
&LIBID_CSSAppServer, // typelib ID containing source interface.
1, // Major version # of LIBID_COMOBJLib. 0> // Minor version # of LIBID_COMOBJLib.
{
public:
CSvrEvent();
CSvrEvent(IServer *pIApplet);
~CSvrEvent(void);
BEGIN_SINK_MAP(CSvrEvent)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000001, ControllerDetected, &info2)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000002, ControllerOnline, &info2)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000003, ControllerOffline, &info2)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000004, DoorStatusChanged, &info4)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000005, PointStatusChanged, &info4_1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000006, ControllerSearchEnd, &info1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000007, NetNodeOnline, &info1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000008, NetNodeOffline, &info1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x00000009, UncommonDoorEvent, &info4_2)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x0000000a, HistoryEvent, &info1_1)
SINK_ENTRY_INFO(IDC_TMPE_ID,__uuidof(IServerEvents), 0x0000000b, UserAreaChanged, &info4_3)
END_SINK_MAP()
// IUnknown methods
ULONG STDMETHODCALLTYPE AddRef(void);
ULONG STDMETHODCALLTYPE Release(void);
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void * *ppvObj);
// 组件发出的事件函数
STDMETHODCALLTYPE ControllerDetected(_bstr_t NodeIName, short CtrlAddr);
STDMETHODCALLTYPE ControllerOnline(_bstr_t NodeName, short CtrlAddr);
STDMETHODCALLTYPE ControllerOffline(_bstr_t NodeName, short CtrlAddr);
STDMETHODCALLTYPE DoorStatusChanged(_bstr_t NodeName, short CtrlAddr, long DoorAddr, long Status);
STDMETHODCALLTYPE PointStatusChanged(_bstr_t NodeName, short CtrlAddr, short PointAddr, long Status);
STDMETHODCALLTYPE ControllerSearchEnd(_bstr_t NodeName);
STDMETHODCALLTYPE NetNodeOnline(_bstr_t NodeName);
STDMETHODCALLTYPE NetNodeOffline(_bstr_t NodeName);
STDMETHODCALLTYPE UncommonDoorEvent(_bstr_t NodeName,WORD EventType,WORD CtrlAddr,WORD DoorAddr);
STDMETHODCALLTYPE HistoryEvent(long Events);
STDMETHODCALLTYPE UserAreaChanged (_bstr_t NodeName, long ZoneNo, long CardNo, short Area);
};
下面是在初始化时引用这个事件类的代码:
COSERVERINFO ServerInfo;
MULTI_QI Results;
ServerInfo.dwReserved1 = 0;
ServerInfo.dwReserved2 = 0;
ServerInfo.pAuthInfo =NULL;
ServerInfo.pwszName = L"192.168.0.106"; //远程服务器机器名
Results.pIID = &IID_IServer;
Results.pItf = NULL;
HRESULT hr;
hr = CoCreateInstanceEx(CLSID_Server,NULL,
CLSCTX_REMOTE_SERVER,&ServerInfo,1,&Results);
if(FAILED(hr))
{
MessageBox(NULL, "Connect to Server failed","Error",MB_OK | MB_ICONSTOP);
return FALSE;
}
Results.pItf->QueryInterface(&m_pServer);
CComPtr<IConnectionPointContainer> pCPC;