欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于VC編寫COM連接點(diǎn)事件的分析介紹

 更新時(shí)間:2013年05月17日 12:30:07   作者:  
本篇文章是對(duì)VC編寫COM連接點(diǎn)事件進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下

COM 中的典型方案是讓客戶端對(duì)象實(shí)例化服務(wù)器對(duì)象,然后調(diào)用這些對(duì)象。然而,沒(méi)有一種特殊機(jī)制的話,這些服務(wù)器對(duì)象將很難轉(zhuǎn)向并回調(diào)到客戶端對(duì)象。COM 連接點(diǎn)便提供了這種特殊機(jī)制,實(shí)現(xiàn)了服務(wù)器和客戶端之間的雙向通信。使用連接點(diǎn),服務(wù)器能夠在服務(wù)器上發(fā)生某些事件時(shí)調(diào)用客戶端。

原理如下圖:

有了連接點(diǎn),服務(wù)器可通過(guò)定義一個(gè)接口來(lái)指定它能夠引發(fā)的事件。服務(wù)器上引發(fā)事件時(shí),要采取操作的客戶端會(huì)向服務(wù)器進(jìn)行自行注冊(cè)。隨后,客戶端會(huì)提供服務(wù)器所定義接口的實(shí)現(xiàn)。

客戶端可通過(guò)一些標(biāo)準(zhǔn)機(jī)制向服務(wù)器進(jìn)行自行注冊(cè)。COM 為此提供了 IConnectionPointContainer 和 IConnectionPoint 接口。

COM 連接點(diǎn)服務(wù)器的客戶端可用 C++ 和 C# 托管代碼來(lái)編寫。C++ 客戶端會(huì)注冊(cè)一個(gè)類的實(shí)例,該類提供了接收器接口的實(shí)現(xiàn)。托管客戶端會(huì)注冊(cè)單個(gè)事件的委托,因而會(huì)按每個(gè)事件通知方法創(chuàng)建單個(gè)接收器,具體參考C#的互操作部分內(nèi)容。

一、連接點(diǎn)程序編寫
1、使用ATL建立組件程序。
2、添加ATL     SIMPLE     OBJECT,支持連接點(diǎn)事件。
注:如果當(dāng)時(shí)沒(méi)有現(xiàn)在連接點(diǎn)事件,可以在.idl文件中手動(dòng)添加。比如

復(fù)制代碼 代碼如下:

 [
       uuid(57CCB7A5-F3B6-4990-91CD-33A82E1AAA46),
       helpstring("IFunEvent dispinterface")
    ]
    dispinterface _IFunEvent
    {
       properties:
           //  事件接口沒(méi)有任何屬性
       methods:
           [id(1), helpstring("方法OnResult")] HRESULT OnResult([out,retval] LONG* retval);
           [id(2), helpstring("方法OnType")] HRESULT OnType([in] LONG nType);
}

3、因?yàn)橹С诌B接點(diǎn)事件,這樣將會(huì)自動(dòng)生成一個(gè)     _XXXEVENT源接口。我們?cè)谄渲性黾酉胍|發(fā)的方法。
4、選擇組件下的事件對(duì)象,彈出對(duì)話框選擇添加方法??梢岳^續(xù)添加多個(gè)方法…
5、實(shí)現(xiàn)方法(其實(shí)組件里只是做方法的申明,客戶調(diào)用時(shí)才實(shí)現(xiàn)這些方法)。實(shí)現(xiàn)時(shí)選中組件/類,按右鍵,在彈出菜單中選中implement     connection....
就會(huì)產(chǎn)生CProxy_xxxEvent類,里面有Fire函數(shù)的實(shí)現(xiàn),都是自動(dòng)生成的。
6、完成組件的其他接口函數(shù)。
組件的連接點(diǎn)編寫比較簡(jiǎn)單,關(guān)鍵是如何在客戶端實(shí)現(xiàn)事件監(jiān)聽(tīng)與接收。在.NET下很容易實(shí)現(xiàn)。但在VC中比較繁瑣。
二、連接點(diǎn)客戶端實(shí)現(xiàn)(VC)
1、包含“工程_i.h”頭文件,引入“工程.tlb”ole庫(kù)文件。比如:
#include "ATLDemo_i.h"
#import "ATLDemo.tlb" named_guids raw_interfaces_only
2、創(chuàng)建一個(gè)類:由_IXXXEvent派生過(guò)來(lái)。(XXX為實(shí)際事件名)
實(shí)現(xiàn)類各個(gè)虛函數(shù)重載,如果_IXXXEvent是IUnkown接口只需要重載QueryInterface、AddRef、Release函數(shù);如果_IXXXEvent是雙向接口需要重載實(shí)現(xiàn)IUnkown接口三個(gè)函數(shù)和IDispatch接口四個(gè)函數(shù)。
實(shí)現(xiàn)事件功能,通過(guò)函數(shù)、用SINK_ENTRY_INFO實(shí)現(xiàn)事件的映射、Invoke函數(shù)里面實(shí)現(xiàn)(通過(guò)事件ID)三種方法之一來(lái)實(shí)現(xiàn)。
用SINK_ENTRY_INFO實(shí)現(xiàn)事件的映射
如:
復(fù)制代碼 代碼如下:

BEGIN_SINK_MAP(CEventSink)
    SINK_ENTRY_INFO(1,DIID__INew01Events,DISPID_MSG,Msg,&MsgInfo)
END_SINK_MAP()

我在組件中定義了一個(gè)Msf函數(shù),所以在這里對(duì)其進(jìn)行消息隱射。然后實(shí)現(xiàn)Msg方法。
3、如何調(diào)用
3.1使用工程支持COM,使用afxoleinit或者CoInitialize/Un CoInitialize
3.2得到組件接口
3.3得到連接點(diǎn)容器,查找連接點(diǎn)。
3.4利用Advise將一個(gè)監(jiān)聽(tīng)對(duì)象傳給組件,這樣當(dāng)事件發(fā)生的時(shí)候事件就會(huì)響應(yīng)。在不使用時(shí),通過(guò)UnAdvise來(lái)斷開連接點(diǎn)事件。同時(shí)也利用AfxConnectionAdvice將監(jiān)聽(tīng)對(duì)象傳給組件接口。
3.5 釋放資源。
具體代碼如下:
復(fù)制代碼 代碼如下:

#pragma once

#include "ATLDemo_i.h"
#import "ATLDemo.tlb" named_guids raw_interfaces_only

class CSkin : public _IFunEvent
{
public:
    CSkin(void);
    ~CSkin(void);
private:
    DWORD       m_dwRefCount;
public:
    STDMETHODIMP Fire_OnType( LONG nType)
    {
       CString    strTemp;
       strTemp.Format(_T("The result is %d"), nType);
       AfxMessageBox(strTemp);
       return S_OK;;
    }
    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
    {
       if (iid == DIID__IFunEvent)
       {
           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;
    }

     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) // 根據(jù)不同的dispIdMember,完成不同的回調(diào)函數(shù),事件函數(shù)的ID編號(hào)
       {
       case 2:
           {
              // 1st param : [in] long lValue.
              VARIANT varlValue;
              long lValue = 0;
              VariantInit(&varlValue);
              VariantClear(&varlValue);
              varlValue = (pDispParams->rgvarg)[0];
              lValue = V_I4(&varlValue);
              Fire_OnType(lValue);
           }
           break;
       default:   break;
       }

       return S_OK;
    }
};

#include "StdAfx.h"
#include "Skin.h"

CSkin::CSkin(void)
{
     m_dwRefCount =0;
}

CSkin::~CSkin(void)
{
}

實(shí)現(xiàn)部分:
復(fù)制代碼 代碼如下:

CoInitialize(NULL);

    CComPtr<IFun> pFun;
    HRESULT hr = pFun.CoCreateInstance(CLSID_Fun);
    if(hr!=S_OK)
    {
       return ;
    }

    IConnectionPointContainer *pCPC;
    hr = pFun->QueryInterface(IID_IConnectionPointContainer,(void **)&pCPC);
    if(!SUCCEEDED(hr))
    {
       return ;
    }
    IConnectionPoint *pCP;
    hr = pCPC->FindConnectionPoint(DIID__IFunEvent,&pCP);
    if ( !SUCCEEDED(hr) )
    {
       return ;
    }
    pCPC->Release();

    IUnknown *pSinkUnk;
    CSkin *pSink = new CSkin();
    hr = pSink->QueryInterface(IID_IUnknown,(void **)&pSinkUnk);
    DWORD dwAdvise;
    hr = pCP->Advise(pSinkUnk,&dwAdvise);//接收器與連接點(diǎn)建立關(guān)聯(lián)

    LONG c = 0;
    pFun->Add(1,5,&c);
    //pCP->Unadvise(dwAdvise) //斷開連接點(diǎn)事件
    pCP->Release();
    pFun.Release();

    CoUninitialize();

相關(guān)文章

  • 利用Matlab復(fù)刻舉牌加油小人生成器

    利用Matlab復(fù)刻舉牌加油小人生成器

    upuptoyou是一款非常有創(chuàng)意的小工具,可以在線生成舉牌小人,看起來(lái)很可愛(ài),也比較有趣,并能用于表白,或節(jié)日送祝福等場(chǎng)景。本文將用Matlab復(fù)刻這一小工具,需要的可以參考一下
    2022-03-03
  • C++實(shí)現(xiàn)發(fā)送郵件和附件功能

    C++實(shí)現(xiàn)發(fā)送郵件和附件功能

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)發(fā)送郵件和附件功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • C語(yǔ)言實(shí)現(xiàn)車輛信息管理系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)車輛信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)車輛信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++中操作符的前置與后置有什么區(qū)別

    C++中操作符的前置與后置有什么區(qū)別

    C 語(yǔ)言提供了豐富的操作符,有:算術(shù)操作符,移位操作符,位操作符,賦值操作符,單目操作符,關(guān)系操作符,邏輯操作符,條件操作符等。接下了讓我們?cè)敿?xì)了解掌握它
    2022-05-05
  • C語(yǔ)言實(shí)現(xiàn)猜數(shù)字的小游戲

    C語(yǔ)言實(shí)現(xiàn)猜數(shù)字的小游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)猜數(shù)字的小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • C++深入講解哈夫曼樹

    C++深入講解哈夫曼樹

    給定N個(gè)權(quán)值作為N個(gè)葉子結(jié)點(diǎn),構(gòu)造一棵二叉樹,若該樹的帶權(quán)路徑長(zhǎng)度達(dá)到最小,稱這樣的二叉樹為最優(yōu)二叉樹,也稱為哈夫曼樹(Huffman Tree)。哈夫曼樹是帶權(quán)路徑長(zhǎng)度最短的樹,權(quán)值較大的結(jié)點(diǎn)離根較近
    2022-05-05
  • 一起來(lái)學(xué)習(xí)C++中remove與erase的理解

    一起來(lái)學(xué)習(xí)C++中remove與erase的理解

    這篇文章主要為大家詳細(xì)介紹了C++的remove與erase,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • c語(yǔ)言內(nèi)存泄漏嚴(yán)重的解決方法

    c語(yǔ)言內(nèi)存泄漏嚴(yán)重的解決方法

    這篇文章主要介紹了c語(yǔ)言內(nèi)存泄漏的解決方法,幫助大家更好的理解和使用c語(yǔ)言開發(fā),感興趣的朋友可以了解下
    2020-09-09
  • C++中新手容易犯的十種編程錯(cuò)誤匯總

    C++中新手容易犯的十種編程錯(cuò)誤匯總

    一段C語(yǔ)言代碼,在編譯、鏈接和運(yùn)行的各個(gè)階段都可能會(huì)出現(xiàn)問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于C++中新手容易犯的十種編程錯(cuò)誤的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之堆排序的優(yōu)化算法

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之堆排序的優(yōu)化算法

    堆排序Heap?Sort就是利用堆進(jìn)行排序的方法,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之堆排序的優(yōu)化算法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04

最新評(píng)論