最近在學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;
}