• <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://m.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
              回復  更多評論
              
            国内精品伊人久久久久| 老男人久久青草av高清| 亚洲精品乱码久久久久66| 伊人色综合久久天天网| 色狠狠久久综合网| av国内精品久久久久影院| 国产69精品久久久久99尤物| 久久久久亚洲AV综合波多野结衣| 伊人久久大香线蕉精品不卡| 亚洲狠狠婷婷综合久久蜜芽| 国内精品久久久久久久coent| 九九精品99久久久香蕉| 久久91精品国产91久久小草| 四虎亚洲国产成人久久精品| 久久免费高清视频| 伊人久久综合无码成人网| 久久久久久国产精品无码下载| 久久99久久99小草精品免视看| 久久精品国产99久久丝袜| 久久精品www人人爽人人| 久久这里只有精品首页| 色偷偷888欧美精品久久久| 久久精品国产亚洲AV蜜臀色欲| 久久毛片免费看一区二区三区| 久久青青草原亚洲av无码app| 色偷偷88欧美精品久久久| 久久99久久99小草精品免视看| 久久久久久伊人高潮影院| 青青草国产97免久久费观看| 欧美一区二区精品久久| 国产∨亚洲V天堂无码久久久| 久久久久久午夜精品| 久久精品成人免费观看97| 日本福利片国产午夜久久| 久久狠狠高潮亚洲精品| 亚洲国产精品无码久久98| 伊人久久大香线蕉成人| 久久综合色老色| 久久久亚洲AV波多野结衣| 久久99精品国产麻豆宅宅| 精品久久久中文字幕人妻|