• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-60  評(píng)論-262  文章-1  trackbacks-0
            當(dāng)年俺為了實(shí)現(xiàn)一個(gè)連接點(diǎn)接收器, 死了俺太多腦細(xì)胞. 今天重新看這一部分內(nèi)容, 實(shí)現(xiàn)了一個(gè)模板, 使用相當(dāng)簡(jiǎn)單, 它使用 ATL 的實(shí)現(xiàn).

            以下是這個(gè)代碼的頭文件 "sinkimpl.h"

            #if !defined( __sinkimpl_h_INCLUDED__ )
            #define __sinkimpl_h_INCLUDED__ 

            #if _MSC_VER > 1000
            #pragma once
            #endif // _MSC_VER > 1000


            template
            <typename T, typename EventInterface, const GUID * evtLibID=NULL >
            class ATL_NO_VTABLE CSinkImpT 
                : 
            public CComObjectRootEx<CComSingleThreadModel>
                , 
            public CComCoClass<CSinkImpT<T, EventInterface, evtLibID>&__uuidof(T)>
                , 
            public IDispatchImpl<EventInterface, &__uuidof(EventInterface), evtLibID>
            {
            public:
                CSinkImpT(){}
                
            virtual ~CSinkImpT(){}

                typedef IDispatchImpl
            <EventInterface, &__uuidof(EventInterface), evtLibID> _parentClass;
                typedef CSinkImpT
            <T, EventInterface, evtLibID> _thisClass;

                STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
                    LCID lcid, WORD wFlags, DISPPARAMS
            * pdispparams, VARIANT* pvarResult,
                    EXCEPINFO
            * pexcepinfo, UINT* puArgErr)
                {
                    T 
            * pThis = static_cast<*>(this);
                    
            return pThis->DoInvoke(dispidMember, riid,
                        lcid, wFlags, pdispparams, pvarResult,
                        pexcepinfo, puArgErr);
                }

                DECLARE_NO_REGISTRY()

                DECLARE_PROTECT_FINAL_CONSTRUCT()

                BEGIN_COM_MAP(_thisClass)
                    COM_INTERFACE_ENTRY(IDispatch)
                    COM_INTERFACE_ENTRY(EventInterface)
                END_COM_MAP();

                STDMETHOD(DoInvoke)(DISPID dispidMember, REFIID riid,
                    LCID lcid, WORD wFlags, DISPPARAMS
            * pdispparams, VARIANT* pvarResult,
                    EXCEPINFO
            * pexcepinfo, UINT* puArgErr)
                {
                    
            return _parentClass::Invoke(dispidMember, riid,
                        lcid, wFlags, pdispparams, pvarResult,
                        pexcepinfo, puArgErr);
                }
            };

            inline HRESULT WINAPI GetConnectPoint(IUnknown 
            * pItf, const IID & rSinkIID, IConnectionPoint ** ppCP)
            {
                HRESULT hr 
            = E_FAIL;
                
            do 
                {
                    
            if (pItf==NULL || ppCP==NULL) { break; }

                    CComQIPtr
            <IConnectionPointContainer> spContainer; 
                    hr 
            = pItf->QueryInterface(&spContainer);
                    
            if (FAILED(hr)) { break; }

                    hr 
            = spContainer->FindConnectionPoint(rSinkIID, ppCP);
                } 
            while (FALSE);
                
            return hr;
            }

            #endif // !defined( __sinkimpl_h_INCLUDED__ )

            將上述內(nèi)容保存為 "sinkimpl.h" 頭文件. 然后將這個(gè)頭文件包含在 stdafx.h 靠下一點(diǎn)的地方. 然后就可以使用這個(gè)類(lèi)模板 CSinkImpT 了.
            來(lái)來(lái)來(lái), 咱定義一個(gè)例子, 用 oleview.exe 查看我們要實(shí)現(xiàn)的針對(duì)某一事件的類(lèi)定義:

            可以看到, 事件接口 _GoRiDiEvents 有一個(gè)事件 Dead 序號(hào)是 1, 據(jù)此我們寫(xiě)下如下實(shí)現(xiàn)代碼.
            #pragma once

            // 1. define my sink class' CLSID, it's must!!! 
            class DECLSPEC_UUID("492194D9-7BEE-422D-AE7C-C43A809F20EC") CSink3;

            // 2. define my sink class, it is derived from class template CSinkImpT
            class ATL_NO_VTABLE CSink3
                : 
            public CSinkImpT<CSink3, _IGoRiDiEvents/*, &__uuidof(__LIANJIEDIANLib)*/>
            {
            public:
                CSink3(
            void){ m_pMain=NULL; }
                
            virtual ~CSink3(void){}

                typedef CSinkImpT
            <CSink3, _IGoRiDiEvents/*, &__uuidof(__LIANJIEDIANLib)*/> _parentClass; 

                STDMETHOD(DoInvoke)(DISPID dispidMember, REFIID riid,
                    LCID lcid, WORD wFlags, DISPPARAMS
            * pdispparams, VARIANT* pvarResult,
                    EXCEPINFO
            * pexcepinfo, UINT* puArgErr)
                {
                    
            // 3. the dispidMember must referenced from .thl file, and you can have a look using oleview.exe
                    switch(dispidMember)
                    {
                    
            case 1
                        
            if( m_pMain ){
                            ::MessageBoxW(m_pMain, pdispparams
            ->rgvarg[0].bstrVal, L"Sink Message", MB_OK);
                        }
                        
            return S_OK;
                    
            default:
                        
            break;
                    }
                    
            return _parentClass::DoInvoke(dispidMember, riid,
                        lcid, wFlags, pdispparams, pvarResult,
                        pexcepinfo, puArgErr);
                }

                HWND m_pMain;
                
            void SetOwner(HWND pDlg) {
                    m_pMain 
            = pDlg;
                }
            };

            將以上內(nèi)容保存為 sink3.h 文件. 就可以在你需要的地方使用這個(gè)接收器了. 接收器的使用相當(dāng)簡(jiǎn)便:
            {
                HRESULT hr 
            = E_FAIL;
                
            do 
                {
                    
            if (m_spGoridi==NULL || m_dwCookie!=0) { break; }

                    CComQIPtr
            <IConnectionPoint> spCP;
                    hr 
            = GetConnectPoint(m_spGoridi, __uuidof(_IGoRiDiEvents), &spCP);
                    
            if (FAILED(hr)){ break; }

                    CComQIPtr
            <IDispatch> spSink;
                    {
                        CComObject
            <CSink3> * pTmp = NULL;
                        hr 
            = CComObject<CSink3>::CreateInstance(&pTmp);
                        
            if (FAILED(hr)){ break; }

                        pTmp
            ->SetOwner(m_hWnd);

                        pTmp
            ->AddRef();
                        hr 
            = pTmp->QueryInterface(&spSink);
                        pTmp
            ->Release();

                        
            if (FAILED(hr)){ break; }
                    }

                    spCP
            ->Advise(spSink, &m_dwCookie); 

                } 
            while (FALSE);
            }

            至此, 可以接收事件了, 注意, 記下 m_dwCookie 值. 到某個(gè)時(shí)候, 我們不想接收事件了, 可以像這樣取消掉它:
            {
                HRESULT hr 
            = E_FAIL;
                
            do {
                    
            if (m_dwCookie==0) { break; }

                    CComQIPtr
            <IConnectionPoint> spCP;

                    hr 
            = GetConnectPoint(m_spGoridi, __uuidof(_IGoRiDiEvents), &spCP); 
                    
            if (FAILED(hr)){ break; }

                    hr 
            = spCP->Unadvise(m_dwCookie);
                    m_dwCookie 
            = 0
                } 
            while (FALSE);
            }

            上面的兩段代碼用到了變量 m_spGoridi, 其定義和實(shí)例化為:

            CComPtr<LIANJIEDIANLib::IGoRiDi> m_spGoridi;
            m_spGoridi.CoCreateInstance(__uuidof(LIANJIEDIANLib::GoRiDi));
             

             

             

            以上實(shí)現(xiàn)的例子代碼在此:
            http://www.shnenglu.com/Files/free2000fly/atlsink.zip

            關(guān)于實(shí)現(xiàn)能響應(yīng)事件的組件的文章, 網(wǎng)上已經(jīng)很多了, 這里就是一篇:
            http://blog.vckbase.com/teacheryang/archive/2005/09/21/12224.html


            PS, 敲完才發(fā)現(xiàn), 以上文章的代碼要作點(diǎn)小修改:
            template<typename T, typename EventInterface, const GUID & evtLibID >
            要改成
            template<typename T, typename EventInterface, const GUID * evtLibID=NULL >
            才能在 VC6 下編譯通過(guò), 因?yàn)?vc6 的C++ 實(shí)現(xiàn)不支持模板參數(shù)是引用, 其它地方也必須做相應(yīng)修正. 供下載用的 zip 文件里已經(jīng)修正了.
            posted on 2009-05-28 18:21 free2000fly 閱讀(4253) 評(píng)論(1)  編輯 收藏 引用

            評(píng)論:
            # re: 一個(gè)標(biāo)準(zhǔn)的 COM 連接點(diǎn)接收器(Sink)的實(shí)現(xiàn), 使用相當(dāng)簡(jiǎn)單!!! 2009-07-20 11:47 | free2000fly
            引入類(lèi)型庫(kù)的語(yǔ)句

            #import "libid:f9152aec-3462-4632-8087-eee3c3cdda35" \
            raw_interfaces_only \
            no_smart_pointers \
            raw_dispinterfaces \
            raw_native_types \
            no_implementation
              回復(fù)  更多評(píng)論
              

            只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            久久久久99精品成人片 | 热RE99久久精品国产66热| 新狼窝色AV性久久久久久| 久久综合久久综合亚洲| 一本久道久久综合狠狠爱| 99精品国产综合久久久久五月天| 亚洲精品乱码久久久久久蜜桃不卡| 久久久久亚洲av无码专区导航| 99久久精品这里只有精品| 久久亚洲国产精品成人AV秋霞| 九九久久自然熟的香蕉图片| 久久婷婷五月综合97色直播| 久久亚洲私人国产精品| 欧洲国产伦久久久久久久| 久久国产亚洲精品无码| 性高朝久久久久久久久久| 久久精品www| 国产A三级久久精品| 久久精品无码免费不卡| 激情伊人五月天久久综合| 久久99热这里只有精品66| 亚洲欧美日韩精品久久| 久久亚洲AV成人无码国产| 麻豆av久久av盛宴av| 久久久久亚洲AV无码专区桃色 | 国产高清美女一级a毛片久久w| 一本久久知道综合久久| 欧美日韩精品久久免费| 久久久青草青青国产亚洲免观| 人人狠狠综合久久亚洲88| 精品久久久久香蕉网| 奇米影视7777久久精品| 综合人妻久久一区二区精品| 一级做a爰片久久毛片毛片| 久久天天躁狠狠躁夜夜av浪潮| 国产精品免费久久| 国产叼嘿久久精品久久| 久久99精品久久久久久噜噜| 成人国内精品久久久久影院VR| 久久久久久久综合日本亚洲| 91久久精品91久久性色|