相关内容搜集自网络:
一、CDialog类响应ActiveX事件的实现
在大多数ATL工程中,客户端为了能够响应服务的事件,往往需要继承于IDispEventImpl或IDispEventSimpleImpl的模板类;由于服务本身实现了IDispatch接口,它可以很方便得通过BEGIN_SINK_MAP和END_SINK_MAP实现对事件的分发响应。但当我们为MFC的对话框里添加一个ActiveX后,会发现尽管CDialog并不继承与这两个模板类,却仍然可以实现对事件的响应;而且简单到似乎仅仅只是添加了BEGIN_EVENTSINK_MAP和END_EVENTSINK_MAP。那么问题就是,服务端既然必须通过IDispatch接口来分发事件,那CDialog的IDispatch接口实现在了哪里?
通过在事件响应函数里下断点,观察CallStack,已经可以比较清楚得看出端倪,实际上这不是CDialog的专利,而已由CWnd实现的,它没有继承IDispatch接口,却包含和一个继承于IDispatch接口的成员,通过这个成员告诉CWnd该调用哪个响应函数;这样大大简化了CWnd的实现。
具体的实现情况是:
1,BEGIN_EVENTSINK_MAP和END_EVENTSINK_MAP的作用仅仅是把事件响应函数放到对话框的窗口函数;
2,CWnd 拥有一个COleControlContainer型成员m_pCtrlCont;
3,m_pCtrlCont拥有多个COleControlSite成员,这样可以保证一个对话框上有多个ActiveX而不会互相干扰;
4,每个COleControlSite拥有一个继承于IDispatch的嵌套类XEventSink及其成员m_xEventSink。通过以下这样一段宏实现:
BEGIN_INTERFACE_PART(EventSink, IDispatch)
INIT_INTERFACE_PART(COleControlSite, EventSink)
STDMETHOD(GetTypeInfoCount)(unsigned int*);
STDMETHOD(GetTypeInfo)(unsigned int, LCID, ITypeInfo**);
STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR*, unsigned int, LCID, DISPID*);
STDMETHOD(Invoke)(DISPID, REFIID, LCID, unsigned short, DISPPARAMS*, VARIANT*, EXCEPINFO*, unsigned int*);
END_INTERFACE_PART(EventSink)
1,BEGIN_EVENTSINK_MAP和END_EVENTSINK_MAP的作用仅仅是把事件响应函数放到对话框的窗口函数;
2,CWnd 拥有一个COleControlContainer型成员m_pCtrlCont;
3,m_pCtrlCont拥有多个COleControlSite成员,这样可以保证一个对话框上有多个ActiveX而不会互相干扰;
4,每个COleControlSite拥有一个继承于IDispatch的嵌套类XEventSink及其成员m_xEventSink。通过以下这样一段宏实现:
BEGIN_INTERFACE_PART(EventSink, IDispatch)
INIT_INTERFACE_PART(COleControlSite, EventSink)
STDMETHOD(GetTypeInfoCount)(unsigned int*);
STDMETHOD(GetTypeInfo)(unsigned int, LCID, ITypeInfo**);
STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR*, unsigned int, LCID, DISPID*);
STDMETHOD(Invoke)(DISPID, REFIID, LCID, unsigned short, DISPPARAMS*, VARIANT*, EXCEPINFO*, unsigned int*);
END_INTERFACE_PART(EventSink)
在Invoke中,实际上就是调用对话框的OnCmdMsg,从而很方便得实现了事件的分发,而对客户端而言却丝毫感觉不到影响。
从这个实现,可以发现使用包含的设计方式往往比继承更具有灵活性;同时也提供了另一种客户端对事件响应的实现方式。实际上,不需要一定要通过宏修改窗口函数,而只要适当修改Invoke令其实现事件分发即可。
ATL中,使用Begin_Sink_map mfc中,使用Begin_eventSink_map。
更多关于网页端、MFC、ATL的dispatch实现
http://blog.csdn.net/kuanghong/article/details/1765119
二、关于参数vtsparam
The vtsParams argument is a space-separated list of values from the VTS_ constants.