一份完整的com組件服務端和客戶端教程

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

}


 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章