最近在学com组件编程 苦于没有没有好的完整的教程 浪费大把时间,尤其是连接点那一块 ,网上很多文章都是 只显示代码的一段,本文更注重 项目的配置,完整如下
参考文章:
http://www.vckbase.com/index.php/wv/1257.html
http://www.cnblogs.com/wubiyu/archive/2009/03/10/1407947.html
http://www.cppblog.com/woaidongmao/archive/2011/01/10/138250.html
服务端
新建ATL项目服务端
添加类
选择ATL简单对象
给接口添加方法
填写方法名务必确定in 还是out 返回指针要是retval
Idl文件中已自动生成代码
接口方法已经好了后面给接口及类添加连接点
添加AddStarted,AddCompleted两个事件后面客户端也会实现这两个事件,由com服务端(com组件来调用客户端的方法)
添加方法跟CFun添加方法一样,这里就不再重复
给CFun类添加连接点
选中事件
确定后,_IFunEvents_CP.h中会自动添加Fire_***方法用于com组件调用客户端事件代码。
完成最后一步 确定什么时候 发出事件 通知客户端
客户端
一个简单的控制台项目就够了
务必勾上ATL头,或者自己添加头文件也可
添加Sink接收器类用于与com组件进行交互,继承于服务端我们定义的_IFunEvents
代码如下:
#pragma once
#include "../ATLComServer/ATLComServer_i.h"
#import "../ATLComServer/Debug/ATLComServer.tlb"named_guids raw_interfaces_only
class CSink : public <span style="color:#FF0000;"><strong>_IFunEvents</strong></span>
{
public:
CSink(void){}
~CSink(void){}
private:
DWORD m_dwRefCount;
public:
HRESULTSTDMETHODCALLTYPE <strong><span style="color:#FF0000;">AdditionStarted</span></strong>()
{
printf("C++SINK: Addition started event fired ... \n");
returnS_OK;
};
HRESULTSTDMETHODCALLTYPE <strong><span style="color:#FF0000;">AdditionCompleted</span></strong>(LONG nResult)
{
printf("C++SINK: Addition completed event fired ... \n");
printf("C++SINK: Addition result: %d \n",nResult);
returnS_OK;
};
HRESULTSTDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
{
if(iid == <span style="color:#FF0000;"><strong>DIID__IFunEvents</strong></span>) //事件接口ID
{
m_dwRefCount++;
*ppvObject= (void *)this;
returnS_OK;
}
if(iid == IID_IUnknown)
{
m_dwRefCount++;
*ppvObject= (void *)this;
returnS_OK;
}
returnE_NOINTERFACE;
}
ULONGSTDMETHODCALLTYPE AddRef()
{
m_dwRefCount++;
returnm_dwRefCount;
}
ULONGSTDMETHODCALLTYPE Release()
{
ULONGl;
l = m_dwRefCount--;
if( 0 == m_dwRefCount)
{
deletethis;
}
returnl;
}
HRESULTSTDMETHODCALLTYPE GetTypeInfoCount(
/*[out] */ __RPC__out UINT *pctinfo)
{
returnS_OK;
}
HRESULTSTDMETHODCALLTYPE GetTypeInfo(
/*[in] */ UINT iTInfo,
/*[in] */ LCID lcid,
/*[out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo)
{
returnS_OK;
}
HRESULTSTDMETHODCALLTYPE 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)
{
returnS_OK;
}
/*[local] */ HRESULT STDMETHODCALLTYPE <span style="color:#FF0000;"><strong>Invoke</strong></span>(
/*[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编号
{
case1:
<span style="color:#FF0000;"><strong> AdditionStarted();</strong></span>
break;
case2:
<span style="color:#FF0000;"><strong>AdditionCompleted(1);</strong></span>
break;
default:
break;
}
returnS_OK;
}
};
Main 主函数代码如下:
// ATLComClient.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include"../ATLComServer/ATLComServer_i.h"
#include "Sink.h"
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
CLSIDclsid;
CLSIDFromProgID(OLESTR("ATLComServer.Fun"),&clsid);
<span style="color:#FF0000;"><strong> CComPtr<IFun> pGetFun;//智能指针</strong></span>
pGetFun.CoCreateInstance(clsid);
HRESULThr = 0;
//query for IConnectionPointContainer interface
IConnectionPointContainer*pCPC;
hr= pGetFun->QueryInterface(
<strong> IID_IConnectionPointContainer</strong>,(void**)&pCPC);
if( !SUCCEEDED(hr) ) { return 0; }
//Using the IConnectionPointContainer,
//get the IConnectionPoint interface
IConnectionPoint*pCP;
hr= pCPC-><span style="color:#FF0000;"><strong>FindConnectionPoint</strong></span>(<span style="color:#FF0000;">DIID__IFunEvents</span>,&pCP);
if( !SUCCEEDED(hr) ) { return 0; }
//Create an instance of the sink object to pass
//to the server
IUnknown*pSinkUnk;
CSink*pSink = new CSink();
if( NULL == pSink ) { return 0; }
//Get the interface pointer to CSink's IUnknown pointer, which you
//will pass to the server
hr= pSink-><strong>QueryInterface</strong>(IID_IUnknown,(void **)&pSinkUnk);
if(!SUCCEEDED(hr)){ return 0; }
DWORDdwAdvise;
hr= pCP-><strong>Advise</strong>(pSinkUnk,&dwAdvise);//接收器与连接点建立关联
if(!SUCCEEDED(hr)){ return 0; }
longnResult = 0;
pGetFun->Add(1,5,&nResult);
pCP-><strong>Unadvise</strong>(dwAdvise);
<strong> pGetFun.Release();//记得release</strong>
CoUninitialize();
return0;
}