方法一:使用MFC映射宏,从CCmdTartget派生子类EventSink
1. .h文件中申明接口、分派ID映射
DECLARE_DISPATCH_MAP()
DECLARE_INTERFACE_MAP()
2. .cpp文件实现接口、分派ID映射
// 映射分派ID
BEGIN_DISPATCH_MAP(cThisClass, CBaseClass)
DISP_FUNCTION_ID(CThisClass,
" ComFunc " ,
DISP_ID,
LocalFuncName,
VARIANT_RETURN_TYPE,
VARIANT_PARAMS_TYPE)
END_DISPATCH_MAP()
// 映射事件接口
BEGIN_INTERFACE_MAP(CThisClass,CBaseClass)
INTERFACE_PART(CThisClass, DIID_IEventXX, Dispatch) // 这里Dispatch为CCmdTart类的一个结构,该宏填充这个结构
END_INTERFACE_MAP()
3. #import ".../组件名.tlb" no_namespace named_guids no_namespace
4. 初始化COM库、Dispatch结构并建立连接
EnableAutomation(); // 同上面的宏一起实现了IDispatch接口
AfxConnectionAdvise(ComObject , DIID__IEventXX, GetIDispatch(FALSE) , FALSE, & m_dwCookie);
5. 实现映射函数(LocalFuncName)
6. 卸载COM库、取消连接
CoUnInitialize();
方法二: 使用ATL映射宏,继承IDsipEventImpl
1. #import ".../组件名.tlb" no_namespace named_guids
2. 实现事件接收类CEventSink
a. 使用ATL宏定义函数信息结构
{
CC_STDCALL, // 调用方式
VT_EMPTY, // 返回类型
1 , // 参数个数
{VT_I4} // 参数类型表
} ;
b. ATL宏映射事件函数
SINK_ENTRY_INFO( 1 , DIID_I, DISP_ID, LocalFunc, & FuncINfo)
END_SINK_MAP()
3. 实例化组件对象和EventSink对象,用EventSink对象或AtlAdvise函数建立连接: EventSink->Advise(...) 或EventSink->DispEventAdvise(...) 或 AtlAdvise(...)
4. 取消连接,销毁对象
#define __EVENTSINK_H
namespace
{
static const int DISPID_SHOW = 1;
static const int DISPID_SHOW2 = 2;
_ATL_FUNC_INFO OnShowInfo =
{
CC_STDCALL, //calling conv
VT_EMPTY,//return value
0 ,//number of arguments
NULL//argumnent types
};
_ATL_FUNC_INFO OnShow2Info =
{
CC_STDCALL, //calling conv
VT_EMPTY,//return value
1 ,//number of arguments
{ VT_I2}//argumnent types
};
}
class CEventSink : public IDispEventImpl < 1 , CEventSink, & DIID__IAtlTest2Events, & LIBID_TEST2Lib >
{
public:
CEventSink(){};
virtual ~CEventSink(){};
void __stdcall OnShow(); //没有参数的情况
void __stdcall OnShow2(short);//有参数的情况
//必须要用SINK_ENTRY_INFO,必须指定参数信息
BEGIN_SINK_MAP(CEventSink)
SINK_ENTRY_INFO(1,DIID_ISimpleCOMEvents,DISPID_SHOW,OnShow,&OnShowInfo)
SINK_ENTRY_INFO(1,DIID_ISimpleCOMEvents,DISPID_SHOW2,OnShow2,&OnShow2Info)
END_SINK_MAP()
} ;
#endif
方法三:自定义EventSink,从IDispatch派生,实现所有的虚方法,在Invoke函数中根据DISP_ID处理回调 (代码略)