• <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 閱讀(4261) 評論(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
              回復  更多評論
              
            午夜精品久久久久久久久| 欧美黑人又粗又大久久久| 色妞色综合久久夜夜| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 久久久久久久尹人综合网亚洲| 中文精品99久久国产 | 久久精品二区| 国产激情久久久久影院小草 | 久久国产热精品波多野结衣AV| 久久久久免费精品国产| 日产精品久久久久久久| 久久91精品国产91久| 久久成人国产精品免费软件| 99久久国产宗和精品1上映| 伊人久久大香线蕉亚洲| 久久亚洲精品人成综合网| 久久精品亚洲中文字幕无码麻豆| 久久久久久久亚洲Av无码| 成人久久综合网| 国产精品99久久不卡| 久久久久久久久66精品片| 久久精品中文字幕大胸| 久久久免费精品re6| 国产午夜久久影院| 久久久精品波多野结衣| 久久99这里只有精品国产| 久久人爽人人爽人人片AV | 久久精品免费一区二区三区| 欧美亚洲另类久久综合| 久久亚洲2019中文字幕| 狠狠综合久久综合88亚洲| 久久综合给合久久狠狠狠97色69| 伊人色综合久久天天| 亚洲人成电影网站久久| 久久av无码专区亚洲av桃花岛| 日韩精品国产自在久久现线拍| 2021久久精品免费观看| 蜜桃麻豆www久久| 性高湖久久久久久久久| 久久国产高清一区二区三区| 亚洲欧美日韩中文久久|