實現步驟
- 添加 ATL 支持: 專案右鍵 → Add ATL Object。
- 實現
IDispEventImpl 接口: 定義事件接收類,映射 DISPID 到處理函數。
- 連接/斷開事件源: 使用
DispEventAdvise / DispEventUnadvise。
核心代碼
EventSink.h
#import "..\Server\Debug\Server.exe" raw_interface_only, no_namespace, named_guids
class CEventSink : public IDispEventImpl<0, CEventSink, &DIID__IObjEvents, &LIBID_SERVERLib, 1, 0>
{
public:
BEGIN_SINK_MAP(CEventSink)
SINK_ENTRY_EX(0, DIID__IObjEvents, 1, cbFunc01)
END_SINK_MAP()
STDMETHOD(cbFunc01)();
};
EventSink.cpp
#include "stdafx.h"
#include "EventSink.h"
STDMETHODIMP CEventSink::cbFunc01()
{
AfxMessageBox(_T("called by Event from dll Server!"));
return S_OK;
}
ClientDlg.cpp - 連接事件
#include "EventSink.h"
void CClientDlg::OnButton1()
{
::CoInitialize(NULL);
{
IObjPtr pObj;
CEventSink* pEventSink = new CEventSink;
pObj.CreateInstance(__uuidof(Obj));
pEventSink->DispEventAdvise(pObj); // 建議連接
pObj->Func01(); // 觸發事件
pEventSink->DispEventUnadvise(pObj); // 取消連接
delete pEventSink;
}
::CoUninitialize();
}
關鍵點總結
IDispEventImpl 模板參數:ID、接收類、DIID、LIBID、版本號。
BEGIN_SINK_MAP 映射 DISPID 到成員函數,函數簽名需匹配 STDMETHOD。
- 生命周期:
Advise 後必須配對 Unadvise,否則導致引用計數洩漏。