一份完整的com组件服务端和客户端教程

COM ATL 同时被 3 个专栏收录
1 篇文章 0 订阅
1 篇文章 0 订阅
2 篇文章 0 订阅

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

}


 


  • 0
    点赞
  • 1
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值