• <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  評論-262  文章-1  trackbacks-0
            當年俺為了實現(xiàn)一個連接點接收器, 死了俺太多腦細胞. 今天重新看這一部分內(nèi)容, 實現(xiàn)了一個模板, 使用相當簡單, 它使用 ATL 的實現(xiàn).

            以下是這個代碼的頭文件 "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" 頭文件. 然后將這個頭文件包含在 stdafx.h 靠下一點的地方. 然后就可以使用這個類模板 CSinkImpT 了.
            來來來, 咱定義一個例子, 用 oleview.exe 查看我們要實現(xiàn)的針對某一事件的類定義:

            可以看到, 事件接口 _GoRiDiEvents 有一個事件 Dead 序號是 1, 據(jù)此我們寫下如下實現(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 文件. 就可以在你需要的地方使用這個接收器了. 接收器的使用相當簡便:
            {
                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 值. 到某個時候, 我們不想接收事件了, 可以像這樣取消掉它:
            {
                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, 其定義和實例化為:

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

             

             

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

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


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

            評論:
            # re: 一個標準的 COM 連接點接收器(Sink)的實現(xiàn), 使用相當簡單!!! 2009-07-20 11:47 | free2000fly
            引入類型庫的語句

            #import "libid:f9152aec-3462-4632-8087-eee3c3cdda35" \
            raw_interfaces_only \
            no_smart_pointers \
            raw_dispinterfaces \
            raw_native_types \
            no_implementation
              回復  更多評論
              
            精产国品久久一二三产区区别 | 美女写真久久影院| 99久久精品日本一区二区免费| 久久久久亚洲AV成人片| 精品国产一区二区三区久久| 久久精品人妻一区二区三区| 久久精品视频一| 久久棈精品久久久久久噜噜| 人人狠狠综合久久亚洲婷婷| 欧美亚洲另类久久综合婷婷| 国内精品久久久久久99| 久久这里有精品视频| 精品久久久久久亚洲精品| 久久久久国产日韩精品网站| 亚洲国产精品无码久久一线| 精品一久久香蕉国产线看播放| 久久久久久久久波多野高潮| 国产亚洲精久久久久久无码AV| 国产A级毛片久久久精品毛片| 精品综合久久久久久88小说| 精品国际久久久久999波多野| 色综合合久久天天给综看| 99久久精品国内| 人妻精品久久久久中文字幕69| 久久午夜福利电影| 伊人丁香狠狠色综合久久| 无码精品久久久天天影视| 国产精品久久久久a影院| 国产69精品久久久久9999| 国产精品久久久久久影院 | 国产成人综合久久综合| 亚洲中文字幕无码久久2017| 人妻精品久久久久中文字幕| 久久久久亚洲精品天堂久久久久久| 久久99精品国产麻豆| 亚洲国产精品久久久天堂| 热久久视久久精品18| 亚洲欧美日韩精品久久亚洲区 | 久久久久久极精品久久久| 久久久久久狠狠丁香| 秋霞久久国产精品电影院|