COM组件:可连接对象的VC实现

来源:互联网 发布:vm centos 桥接 编辑:程序博客网 时间:2024/06/06 13:21

我们之前使用的COM组件都是由客户端发起请求,而COM组件提供服务,这样的通信都是单向的,但是有时我们需要双向的通信,比如当一个已经提供服务的COM组件对象触发某个保留的事件时,在前一段时间我们并不知道该怎么做,而现在明确了,但是COM组件已经提供服务,我们对于该事件的处理只能在客户端实现,这时候可连接对象就有了它用武之地了。现在我们说说可连接对象是怎么实现的吧

第一步建立ATL项目,暂时命名为link_obj吧,然后添加ATL简单对象,sobj,这里需要注意的是,要支持连接点,

:想到会自动生成一个_IsobjEvents事件接口,当然还有相应的DIID___IsobjEvents,这个接口就是出接口也就是说,该接口是要我们在客户端实现的接口,为该接口添

加测试成员函数HRESULT Msg,为了添加该成员函数,我们需要将idl以及link_obj_i.h文件中的接口定义都要进行改变,也就是说接口的定义涉及到着两个文件,在idl

中添加

importlib("stdole2.tlb");[uuid(9DB001A9-2F50-42A5-BE06-6EC2A8111A58)]dispinterface _IsobjEvents{properties:methods:[id(1)] HRESULT Msg();};

我们只需要注意添加Msg这一行,

在link_obj_i.h文件中则添加

#if defined(__cplusplus) && !defined(CINTERFACE)    MIDL_INTERFACE("9DB001A9-2F50-42A5-BE06-6EC2A8111A58")    _IsobjEvents : public IDispatch    {STDMETHOD(Msg)();    };    

为了测试,Msg函数要在Advise即连接时执行,那么我们要做的操作就是

STDMETHOD(Advise)(IUnknown *pUnkSink,            /* [out] */ __RPC__out DWORD *pdwCookie){_IsobjEvents*he=static_cast<_isobjevents>(pUnkSink);he->Msg();return S_OK;}

这样启动生成即可,就得到了.dll文件,现在我们要实现的就是客户端的程序了。

#include<iostream>using namespace std;#include"D:\project\link_obj\link_obj\link_obj_i.c"#include"D:\project\link_obj\link_obj\link_obj_i.h"class CSkin : public _IsobjEvents{public:CSkin(void){}~CSkin(void){}private:DWORD m_dwRefCount;public:HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject){if (iid == DIID__IsobjEvents){m_dwRefCount++;*ppvObject = (void *)this;return S_OK;}if (iid == IID_IUnknown){m_dwRefCount++; *ppvObject = (void *)this;return S_OK;}return E_NOINTERFACE;}ULONG STDMETHODCALLTYPE AddRef(){m_dwRefCount++;return m_dwRefCount;}ULONG STDMETHODCALLTYPE Release(){ULONG l;l = m_dwRefCount--;if ( 0 == m_dwRefCount){delete this;}return l;}HRESULT STDMETHODCALLTYPE GetTypeInfoCount( /* [out] */ __RPC__out UINT *pctinfo){return S_OK;}HRESULT STDMETHODCALLTYPE GetTypeInfo( /* [in] */ UINT iTInfo,/* [in] */ LCID lcid,/* [out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo){return S_OK;}STDMETHOD(Msg)(){::MessageBoxA(NULL,"正在执行Msg函数",0,0);return S_OK;}HRESULT STDMETHODCALLTYPE GetIDsOfNames( /* [in] */ __RPC__in REFIID riid,/* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,/* [range][in] */ UINT cNames,/* [in] */ LCID lcid,/* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID *rgDispId){return S_OK;}/* [local] */ HRESULT STDMETHODCALLTYPE Invoke( /* [in] */ DISPID dispIdMember,/* [in] */ REFIID riid,/* [in] */ LCID lcid,/* [in] */ WORD wFlags,/* [out][in] */ DISPPARAMS *pDispParams,/* [out] */ VARIANT *pVarResult,/* [out] */ EXCEPINFO *pExcepInfo,/* [out] */ UINT *puArgErr){switch(dispIdMember) // 根据不同的dispIdMember,完成不同的回调函数,事件函数的ID编号{case 2:{// 1st param : [in] long lValue.}break;default: break;}return S_OK;}};int _tmain(int argc, _TCHAR* argv[]){::CoInitialize(NULL);//创建COM对象实例IClassFactory*pcf=NULL;HRESULT hr=::CoGetClassObject(CLSID_sobj,CLSCTX_ALL,NULL,IID_IClassFactory,(void**)&pcf);Isobj* obj=NULL;hr=pcf->CreateInstance(NULL,IID_Isobj,(void**)&obj);pcf->Release();IConnectionPointContainer*ICPC=NULL;hr=obj->QueryInterface(IID_IConnectionPointContainer,(void**)&ICPC);IConnectionPoint*ICP=NULL;hr=ICPC->FindConnectionPoint(DIID__IsobjEvents,&ICP);CSkin *psk=new CSkin();IUnknown* pUk=NULL;hr=psk->QueryInterface(IID_IUnknown,(void**)&pUk);DWORD dw;ICP->Advise(pUk,&dw);ICP->Unadvise(dw);::CoUninitialize();return 0;}

连接过程可以自己写,也可以使用系统默认的链接函数,均可

原创粉丝点击