COM连接点 - 一个COM接口实现多个连接点(3)
来源:互联网 发布:网络综合布线设计方案 编辑:程序博客网 时间:2024/06/06 06:42
之前讲到一个COM接口可以实现多个连接点。我们就来写个例子。
其实,我还真不知道怎么用ATL向导来实现多个连接点,我们这次就手工改吧。我觉得手工来修改还可以提高对COM的理解,多用用手工还是有好处的。
IDL中增加一个接口_IMyCarEvents2
打开IDL文件,增加以下代码(guid是用windows自带的生成器生成的)
[uuid(5A745470-8950-4a9b-B624-5D76F1BB28C9)]dispinterface _IMyCarEvents2{properties:methods: [id(1)] HRESULT NeedMoreGas(); };
现在就变成了
library MyComLib{importlib("stdole2.tlb");[uuid(2CF347A8-63ED-4CE0-8A6D-F98D60C98B8C)]dispinterface _IMyCarEvents{properties:methods: [id(1)] HRESULT OnStop([in] FLOAT Distance); }; [uuid(5A745470-8950-4a9b-B624-5D76F1BB28C9)]dispinterface _IMyCarEvents2{properties:methods: [id(1)] HRESULT NeedMoreGas(); };[uuid(DA6770F3-CBB6-4F34-A137-2B02A27AB219)]coclass MyCar{[default] interface IMyCar;[default, source] dispinterface _IMyCarEvents;};};
增加一个proxy类
template<class T>class CProxy_IMyCarEvents2 : public ATL::IConnectionPointImpl < T, &__uuidof(_IMyCarEvents2) >{public: HRESULT Fire_NeedMoreGas() { HRESULT hr = S_OK; T * pThis = static_cast<T *>(this); int cConnections = m_vec.GetSize(); for (int iConnection = 0; iConnection < cConnections; iConnection++) { pThis->Lock(); CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection); pThis->Unlock(); IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p); if (pConnection) { CComVariant varResult; DISPPARAMS params = { NULL, NULL, 0, 0 }; hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, &varResult, NULL, NULL); } } return hr; }};
修改对应COM类来支持新的连接点
主要就是:
1. 从新连接点的代理类继承
2. CONNECTION POINT MAP那里加上新的连接点。
class ATL_NO_VTABLE CMyCar :public CComObjectRootEx<CComSingleThreadModel>,public CComCoClass<CMyCar, &CLSID_MyCar>,public IConnectionPointContainerImpl<CMyCar>,public CProxy_IMyCarEvents<CMyCar>, public CProxy_IMyCarEvents2<CMyCar>, // 支持新的连接点public IDispatchImpl<IMyCar, &IID_IMyCar, &LIBID_MyComLib, /*wMajor =*/ 1, /*wMinor =*/ 0>{public:CMyCar(){}DECLARE_REGISTRY_RESOURCEID(IDR_MYCAR)BEGIN_COM_MAP(CMyCar)COM_INTERFACE_ENTRY(IMyCar)COM_INTERFACE_ENTRY(IDispatch)COM_INTERFACE_ENTRY(IConnectionPointContainer)END_COM_MAP()BEGIN_CONNECTION_POINT_MAP(CMyCar)CONNECTION_POINT_ENTRY(__uuidof(_IMyCarEvents)) CONNECTION_POINT_ENTRY(__uuidof(_IMyCarEvents2)) // 支持新的连接点END_CONNECTION_POINT_MAP()DECLARE_PROTECT_FINAL_CONSTRUCT()HRESULT FinalConstruct(){return S_OK;}void FinalRelease(){}public: STDMETHOD(Run)();};
RUN函数触发新连接点的一个事件:
STDMETHODIMP CMyCar::Run(){ // TODO: Add your implementation code here this->Fire_OnStop(1000); this->Fire_NeedMoreGas(); return S_OK;}
客户端修改
增加一个新的sink类
class CSink2 :public CComObjectRoot,public _IMyCarEvents2{BEGIN_COM_MAP(CSink2) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(_IMyCarEvents2)END_COM_MAP()public: virtual ~CSink2(){ } STDMETHODIMP GetTypeInfoCount(UINT *pctinfo) { return E_NOTIMPL; } STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { return E_NOTIMPL; } STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { return E_NOTIMPL; } STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { printf("sink, id: %d", dispIdMember); return S_OK; }};
然后挂载
CComObject<CSink2>* sinkptr2 = nullptr; CComObject<CSink2>::CreateInstance(&sinkptr2); AtlAdvise(spCar, sinkptr2, __uuidof(_IMyCarEvents2), &cookies);
跑一下,就会发现2个sink对象的Invoke都被调用了,成功。
注意:一个sink类不能处理2个连接点。我试了一下一个sink了继承2个连接点接口,编译都报错了。
错误如下:
1>d:\study\testcom\testcom\testcom.cpp(22): error C2594: 'static_cast' : ambiguous conversions from 'CSink::_ComMapClass *' to 'IDispatch *'
1>d:\study\testcom\testcom\testcom.cpp(81): error C2594: 'argument' : ambiguous conversions from 'ATL::CComObject<CSink> *' to 'IUnknown *'
不知道是我搞错了,还是确实不支持。不过,我觉得一个sink类处理一个连接点还是合理的。不然全放一起,也不好。
- COM连接点 - 一个COM接口实现多个连接点(3)
- COM连接点 - Part III - 一个COM接口实现多个连接点
- Com连接点
- 体会COM连接点与实现接收器!
- com连接点方式的向导实现
- COM 连接点事件讲解
- COM 连接点事件 转
- COM 多线程连接点调用
- COM 进程外连接点
- com连接点事件浅析
- COM连接点 - 基本原理(2)
- COM连接点事件event
- COM 使用多线程发送连接点事件的实现
- COM连接点C++客户使用注意事项
- VC编写COM连接点事件
- C++ 调用COM连接点步骤
- VC编写COM连接点事件
- COM连接点 - Part I - 基本原理
- linux编程--默认参数
- 语言概念的基本模型
- Android:scaleType属性
- Apache Maven 入门篇(下)
- [SC-02]通过拖拽导入文件
- COM连接点 - 一个COM接口实现多个连接点(3)
- Caused by: java.lang.ClassNotFoundException[android的终极解决错误]
- IBM MQ 7.5 域环境配置问题处理
- OpenGL 坐标转换
- datagridview控件转datatable对象
- Marathon - ZOJ 2683 dp
- android AsyncTask介绍
- Unity3D游戏开发之刀光剑影特效如何实现
- Python mysql 数据库操作