亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

基于VC編寫COM連接點事件的分析介紹

2020-01-26 16:12:07
字體:
來源:轉載
供稿:網友

COM 中的典型方案是讓客戶端對象實例化服務器對象,然后調用這些對象。然而,沒有一種特殊機制的話,這些服務器對象將很難轉向并回調到客戶端對象。COM 連接點便提供了這種特殊機制,實現了服務器和客戶端之間的雙向通信。使用連接點,服務器能夠在服務器上發生某些事件時調用客戶端。

原理如下圖:

有了連接點,服務器可通過定義一個接口來指定它能夠引發的事件。服務器上引發事件時,要采取操作的客戶端會向服務器進行自行注冊。隨后,客戶端會提供服務器所定義接口的實現。

客戶端可通過一些標準機制向服務器進行自行注冊。COM 為此提供了 IConnectionPointContainer 和 IConnectionPoint 接口。

COM 連接點服務器的客戶端可用 C++ 和 C# 托管代碼來編寫。C++ 客戶端會注冊一個類的實例,該類提供了接收器接口的實現。托管客戶端會注冊單個事件的委托,因而會按每個事件通知方法創建單個接收器,具體參考C#的互操作部分內容。

一、連接點程序編寫
1、使用ATL建立組件程序。
2、添加ATL     SIMPLE     OBJECT,支持連接點事件。
注:如果當時沒有現在連接點事件,可以在.idl文件中手動添加。比如

復制代碼 代碼如下:

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

3、因為支持連接點事件,這樣將會自動生成一個     _XXXEVENT源接口。我們在其中增加想要觸發的方法。
4、選擇組件下的事件對象,彈出對話框選擇添加方法。可以繼續添加多個方法…
5、實現方法(其實組件里只是做方法的申明,客戶調用時才實現這些方法)。實現時選中組件/類,按右鍵,在彈出菜單中選中implement     connection....
就會產生CProxy_xxxEvent類,里面有Fire函數的實現,都是自動生成的。
6、完成組件的其他接口函數。
組件的連接點編寫比較簡單,關鍵是如何在客戶端實現事件監聽與接收。在.NET下很容易實現。但在VC中比較繁瑣。
二、連接點客戶端實現(VC)
1、包含“工程_i.h”頭文件,引入“工程.tlb”ole庫文件。比如:
#include "ATLDemo_i.h"
#import "ATLDemo.tlb" named_guids raw_interfaces_only
2、創建一個類:由_IXXXEvent派生過來。(XXX為實際事件名)
實現類各個虛函數重載,如果_IXXXEvent是IUnkown接口只需要重載QueryInterface、AddRef、Release函數;如果_IXXXEvent是雙向接口需要重載實現IUnkown接口三個函數和IDispatch接口四個函數。
實現事件功能,通過函數、用SINK_ENTRY_INFO實現事件的映射、Invoke函數里面實現(通過事件ID)三種方法之一來實現。
用SINK_ENTRY_INFO實現事件的映射
如:
復制代碼 代碼如下:

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

我在組件中定義了一個Msf函數,所以在這里對其進行消息隱射。然后實現Msg方法。
3、如何調用
3.1使用工程支持COM,使用afxoleinit或者CoInitialize/Un CoInitialize
3.2得到組件接口
3.3得到連接點容器,查找連接點。
3.4利用Advise將一個監聽對象傳給組件,這樣當事件發生的時候事件就會響應。在不使用時,通過UnAdvise來斷開連接點事件。同時也利用AfxConnectionAdvice將監聽對象傳給組件接口。
3.5 釋放資源。
具體代碼如下:
復制代碼 代碼如下:

#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) // 根據不同的dispIdMember,完成不同的回調函數,事件函數的ID編號
       {
       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)
{
}

實現部分:
復制代碼 代碼如下:

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);//接收器與連接點建立關聯

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

    CoUninitialize();

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产一区二区三区精品久久久| 青青久久av北条麻妃海外网| 国产成人亚洲综合| 久久av资源网站| 国产精品一二区| 欧美大胆在线视频| 国产精品白丝jk喷水视频一区| 欧美成人性色生活仑片| 日韩欧美亚洲成人| 亚洲丝袜一区在线| 中文字幕日韩在线视频| 青青草原成人在线视频| 国产成人亚洲综合| 亚洲电影成人av99爱色| 久久手机精品视频| 成人精品视频久久久久| 最新国产精品亚洲| www日韩欧美| 欧美激情一级精品国产| 最新亚洲国产精品| 欧美日韩亚洲网| 91产国在线观看动作片喷水| 毛片精品免费在线观看| 亚洲欧美国产视频| 亚洲精品电影久久久| 久久久久一本一区二区青青蜜月| 狠狠色狠狠色综合日日小说| 日韩中文综合网| 久久天天躁狠狠躁夜夜躁| 波霸ol色综合久久| 久久免费视频在线观看| 91在线观看免费高清完整版在线观看| 国产亚洲美女精品久久久| 国产精品a久久久久久| 欧美激情视频一区| 亚洲自拍偷拍在线| 韩国一区二区电影| 成人情趣片在线观看免费| 国产精品观看在线亚洲人成网| 欧美一区二区三区艳史| 欧美老肥婆性猛交视频| 日韩在线视频网站| 欧美激情视频在线免费观看 欧美视频免费一| 久热国产精品视频| 欧美精品在线看| 欧美在线观看视频| 国产亚洲精品久久久久久牛牛| 欧美大人香蕉在线| 日韩免费在线观看视频| 欧美日韩国产中文字幕| 久久久久久高潮国产精品视| 九九久久久久久久久激情| 日本久久久久久久久| 亚洲成年人在线播放| 最近2019年中文视频免费在线观看| 欧美国产日韩一区| 国产成人免费91av在线| 欧美大片大片在线播放| 亚洲综合中文字幕在线观看| 久久香蕉国产线看观看av| 国语自产精品视频在免费| 亚洲国产另类 国产精品国产免费| 日韩经典中文字幕在线观看| 在线观看成人黄色| 久久久精品2019中文字幕神马| 亚洲天堂网在线观看| 国产成人精品免高潮在线观看| 7m第一福利500精品视频| 91色在线观看| 久久精品视频中文字幕| 最新国产精品拍自在线播放| 国产精品三级久久久久久电影| 国产aⅴ夜夜欢一区二区三区| 成人美女免费网站视频| 亚洲最大福利视频网| 欧美日韩黄色大片| 国产ts人妖一区二区三区| 亚洲成人动漫在线播放| 国产精品三级在线| 欧美性猛交xxxx乱大交| 九九精品在线观看| 国产婷婷成人久久av免费高清| 国产一区二区视频在线观看| 欧美激情亚洲另类| www.日韩av.com| 一本一本久久a久久精品牛牛影视| 精品亚洲国产成av人片传媒| 欧美片一区二区三区| 欧美精品www| 91po在线观看91精品国产性色| 欧美性理论片在线观看片免费| 精品久久中文字幕久久av| 色综合影院在线| 日本国产高清不卡| 国产精品白嫩美女在线观看| 欧美日本高清视频| 国产亚洲精品久久久久动| 国产精品欧美一区二区三区奶水| 亚洲色图17p| 国产成人福利夜色影视| 欧美成人黄色小视频| 亚洲国产日韩一区| 欧美成人亚洲成人日韩成人| 国产日产久久高清欧美一区| 欧美高清在线观看| 欧美黄色片在线观看| 精品欧美国产一区二区三区| 黄色一区二区在线观看| 亚洲精品视频网上网址在线观看| 国产精品无码专区在线观看| 久久91精品国产91久久久| 欧美与欧洲交xxxx免费观看| 欧美中文字幕在线| 久久免费精品视频| 国产免费一区视频观看免费| 日本91av在线播放| 欧美午夜美女看片| 久久久人成影片一区二区三区| 欧美黑人巨大精品一区二区| 国产亚洲精品美女久久久| 亚洲一级免费视频| 九九精品在线视频| 欧美一区深夜视频| 黑丝美女久久久| 北条麻妃在线一区二区| 日产精品99久久久久久| 日韩视频在线一区| 伊人久久久久久久久久| 欧美夫妻性生活视频| 国产精品一区二区3区| 国产精品高潮呻吟久久av黑人| 国产福利视频一区| 国产精品久久久久久久久久免费| 精品国产一区二区在线| 国产精品96久久久久久| 久久影院资源站| 国产精品久久国产精品99gif| 国产女人18毛片水18精品| 国产国语videosex另类| 国产精品美女免费看| 久久精品成人欧美大片| 国产免费一区二区三区在线观看| 欧美日韩一二三四五区| 97超碰蝌蚪网人人做人人爽| 一区二区三区视频免费在线观看| 亚洲人成在线观看网站高清| 57pao成人国产永久免费| 97超视频免费观看| 久久伊人精品天天| 国产精品国产自产拍高清av水多| 亚洲图片制服诱惑| 国产精品一香蕉国产线看观看| 岛国精品视频在线播放| 欧美视频在线观看 亚洲欧| 久久久免费高清电视剧观看| 欧美视频在线视频| 国语自产精品视频在免费| 日本一区二区在线播放| 久久久久久久一区二区三区| 欧美人交a欧美精品| 亚洲国产成人精品久久久国产成人一区| 国产主播精品在线| 成人信息集中地欧美| 日韩视频免费看|