• <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
            當年俺為了實現一個連接點接收器, 死了俺太多腦細胞. 今天重新看這一部分內容, 實現了一個模板, 使用相當簡單, 它使用 ATL 的實現.

            以下是這個代碼的頭文件 "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__ )

            將上述內容保存為 "sinkimpl.h" 頭文件. 然后將這個頭文件包含在 stdafx.h 靠下一點的地方. 然后就可以使用這個類模板 CSinkImpT 了.
            來來來, 咱定義一個例子, 用 oleview.exe 查看我們要實現的針對某一事件的類定義:

            可以看到, 事件接口 _GoRiDiEvents 有一個事件 Dead 序號是 1, 據此我們寫下如下實現代碼.
            #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;
                }
            };

            將以上內容保存為 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));
             

             

             

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

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


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

            評論:
            # re: 一個標準的 COM 連接點接收器(Sink)的實現, 使用相當簡單!!! 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
              回復  更多評論
              
            国产亚洲精午夜久久久久久| 亚洲国产精品18久久久久久| 97精品国产97久久久久久免费| 成人资源影音先锋久久资源网| 99久久国产免费福利| 久久精品亚洲男人的天堂| 欧美久久久久久| 久久久久国产精品熟女影院| 久久精品无码一区二区三区| 亚洲欧美久久久久9999| 久久亚洲精品成人av无码网站| 99久久免费只有精品国产| 久久天天躁夜夜躁狠狠躁2022| 97久久天天综合色天天综合色hd| 久久天天躁狠狠躁夜夜av浪潮 | 国产一区二区精品久久岳| 国内精品综合久久久40p| 国产精品内射久久久久欢欢| 色偷偷偷久久伊人大杳蕉| 欧美午夜精品久久久久久浪潮| 国产精品99久久99久久久| 2021国产精品久久精品| 久久久精品国产Sm最大网站| 国产午夜久久影院| 久久不见久久见免费视频7| 久久精品国产2020| 伊人伊成久久人综合网777| 精品一久久香蕉国产线看播放| 精品999久久久久久中文字幕| 久久亚洲春色中文字幕久久久| 亚洲国产一成久久精品国产成人综合| 国产成人精品久久免费动漫| 亚洲伊人久久大香线蕉综合图片| 亚洲精品99久久久久中文字幕| 久久成人18免费网站| 久久精品中文字幕有码| 久久97久久97精品免视看秋霞| 国产精品欧美久久久久无广告| 99久久婷婷国产一区二区 | 精品人妻伦九区久久AAA片69 | 国产A三级久久精品|