WebBroswer2 事件处理

 这两天写一个辅助工具,用到了WebBrowser2控件,需要对DIID_DWebBrowserEvents2事件、DIID_HTMLDocumentEvents2进行处理
ATL提供了IDispEventSimpleImpl模板来简化事件处理,但是这个模板只能绑定一个事件,google了半天也没有找到好的解决方案,索性参考IDispEventSimpleImpl DIY了一个EasyDispEventImpl模板代码如下:

 

    1. struct EVENT_DIID_ENTRY
    2. {   
    3.     const IID* piid;
    4. };
    5. #define BEGIN_EVENT_IID_MAP(_class)/
    6.     typedef _class _GetEventIIDMapFinder;/
    7.     static const EVENT_DIID_ENTRY * _GetEventIIDMap()/
    8.     {/
    9.         typedef _class _atl_event_classtype;/
    10.         static const EVENT_DIID_ENTRY __map[] = {
    11. #define EVENT_IID_ENTRY(iid) {&iid},
    12. #define END_EVENT_IID_MAP() /
    13.     {NULL} }; return __map;/
    14. }
    15. class CWebBrowser2EventsBase
    16. {
    17. protected:
    18.     static _ATL_FUNC_INFO StatusTextChangeStruct;
    19.     static _ATL_FUNC_INFO TitleChangeStruct;
    20.     static _ATL_FUNC_INFO PropertyChangeStruct;
    21.     static _ATL_FUNC_INFO OnQuitStruct;
    22.     static _ATL_FUNC_INFO OnToolBarStruct;
    23.     static _ATL_FUNC_INFO OnMenuBarStruct;
    24.     static _ATL_FUNC_INFO OnStatusBarStruct;
    25.     static _ATL_FUNC_INFO OnFullScreenStruct;
    26.     static _ATL_FUNC_INFO OnTheaterModeStruct;
    27.     static _ATL_FUNC_INFO DownloadBeginStruct;
    28.     static _ATL_FUNC_INFO DownloadCompleteStruct;
    29.     static _ATL_FUNC_INFO NewWindow2Struct; 
    30.     static _ATL_FUNC_INFO CommandStateChangeStruct;
    31.     static _ATL_FUNC_INFO BeforeNavigate2Struct;
    32.     static _ATL_FUNC_INFO ProgressChangeStruct;
    33.     static _ATL_FUNC_INFO NavigateComplete2Struct;
    34.     static _ATL_FUNC_INFO DocumentComplete2Struct;
    35.     static _ATL_FUNC_INFO OnVisibleStruct;
    36.     static _ATL_FUNC_INFO SetSecureLockIconStruct;
    37.     static _ATL_FUNC_INFO NavigateErrorStruct;
    38.     static _ATL_FUNC_INFO PrivacyImpactedStateChangeStruct;
    39.     //static _ATL_FUNC_INFO FileDownloadStruct;   // Unsafe to use
    40.     //static _ATL_FUNC_INFO WindowClosingStruct;
    41.     static _ATL_FUNC_INFO KeyUpEventStruct; 
    42.     static _ATL_FUNC_INFO MouseOverEventStruct; 
    43.     static _ATL_FUNC_INFO ClickEventStruct;     
    44.     static _ATL_FUNC_INFO DbClickEventStruct;       
    45.     static _ATL_FUNC_INFO MouseOutEventStruct;      
    46.     
    47. };
    48. template <UINT nID, class T>
    49. class ATL_NO_VTABLE EasyDispEventImpl
    50. {
    51.     DWORD m_dwBrowserEventCookie;
    52.     DWORD m_dwDocumentEventCookie;
    53. public:
    54.     EasyDispEventImpl():m_dwBrowserEventCookie(0xFEFEFEFE),m_dwDocumentEventCookie(0xFEFEFEFE)
    55.     {}
    56.     STDMETHOD(_LocDEQueryInterface)(REFIID riid, void ** ppvObject)
    57.     {
    58.         ATLASSERT(ppvObject != NULL);
    59.         if (ppvObject == NULL)
    60.             return E_POINTER;
    61.         *ppvObject = NULL;
    62.         if (InlineIsEqualGUID(riid, IID_NULL))
    63.             return E_NOINTERFACE;
    64.         const EVENT_DIID_ENTRY * pMap = T::_GetEventIIDMap();
    65.         const EVENT_DIID_ENTRY * pFound = NULL;
    66.         while (pMap->piid != NULL)
    67.         {
    68.             if(InlineIsEqualGUID(riid,*pMap->piid))
    69.             {
    70.                 pFound = pMap;
    71.                 break;
    72.             }
    73.             pMap++;
    74.         }
    75.         if (pFound || InlineIsEqualUnknown(riid) || InlineIsEqualGUID(riid, __uuidof(IDispatch)))
    76.         {
    77.             *ppvObject = this;
    78.             AddRef();
    79. #ifdef _ATL_DEBUG_INTERFACES
    80.             _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, _T("IDispEventImpl"), riid);
    81. #endif // _ATL_DEBUG_INTERFACES
    82.             return S_OK;
    83.         }
    84.         else
    85.             return E_NOINTERFACE;
    86.     }
    87.     // These are here only to support use in non-COM objects    
    88.     virtual ULONG STDMETHODCALLTYPE AddRef()
    89.     {
    90.         return 1;
    91.     }
    92.     virtual ULONG STDMETHODCALLTYPE Release()
    93.     {
    94.         return 1;
    95.     }
    96.     STDMETHOD(GetTypeInfoCount)(UINT/*pctinfo*/)
    97.     {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetTypeInfoCount"));}
    98.     STDMETHOD(GetTypeInfo)(UINT /*itinfo*/LCID /*lcid*/, ITypeInfo** /*pptinfo*/)
    99.     {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetTypeInfo"));}
    100.     STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, LPOLESTR* /*rgszNames*/UINT /*cNames*/,
    101.         LCID /*lcid*/, DISPID* /*rgdispid*/)
    102.     {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetIDsOfNames"));}
    103.     STDMETHOD(Invoke)(DISPID dispidMember, REFIID /*riid*/,
    104.         LCID lcid, WORD /*wFlags*/, DISPPARAMS* pdispparams, VARIANT* pvarResult,
    105.         EXCEPINFO* /*pexcepinfo*/UINT/*puArgErr*/)
    106.     {
    107.         const _ATL_EVENT_ENTRY<T>* pMap = T::_GetSinkMap();
    108.         const _ATL_EVENT_ENTRY<T>* pFound = NULL;       
    109.         while (pMap->piid != NULL)
    110.         {
    111.             const EVENT_DIID_ENTRY * pEvts = T::_GetEventIIDMap();
    112.             const EVENT_DIID_ENTRY * pFoundEvt = NULL;
    113.             while (pEvts->piid != NULL)
    114.             {
    115.                 if(InlineIsEqualGUID(*(pMap->piid),*(pEvts->piid)))
    116.                 {
    117.                     pFoundEvt = pEvts;
    118.                     break;
    119.                 }
    120.                 pEvts++;
    121.             }
    122.             if ((pMap->nControlID == nID) && (pMap->dispid == dispidMember) && pFoundEvt )
    123.             {               
    124.                 pFound = pMap;
    125.                 break;
    126.             }
    127.             pMap++;
    128.         }
    129.         if (pFound == NULL)
    130.             return S_OK;
    131.         _ATL_FUNC_INFO info;
    132.         _ATL_FUNC_INFO* pInfo;
    133.         if (pFound->pInfo != NULL)
    134.             pInfo = pFound->pInfo;
    135.         else
    136.         {
    137.             pInfo = &info;
    138.             HRESULT hr = GetFuncInfoFromId(*(pFound->piid), dispidMember, lcid, info);
    139.             if (FAILED(hr))
    140.                 return S_OK;
    141.         }
    142.         return InvokeFromFuncInfo(pFound->pfn, *pInfo, pdispparams, pvarResult);
    143.     }
    144.     //Helper for invoking the event
    145.     HRESULT InvokeFromFuncInfo(void (__stdcall T::*pEvent)(), _ATL_FUNC_INFO& info, DISPPARAMS* pdispparams, VARIANT* pvarResult)
    146.     {
    147.         ATLASSERT(pdispparams->cArgs == (UINT)info.nParams);
    148.         T* pT = static_cast<T*>(this);
    149.         // If this assert occurs, then add 
    150.         // #define _ATL_MAX_VARTYPES nnnn
    151.         // before including atlcom.h
    152.         ATLASSERT(info.nParams <= _ATL_MAX_VARTYPES);
    153.         if (info.nParams > _ATL_MAX_VARTYPES)
    154.         {
    155.             return E_FAIL;
    156.         }
    157.         VARIANTARG* rgVarArgs[_ATL_MAX_VARTYPES];
    158.         VARIANTARG** pVarArgs = info.nParams ? rgVarArgs : 0;
    159.         UINT nIndex = 0;
    160. #ifndef _ATL_IGNORE_NAMED_ARGS
    161.         for (nIndex; nIndex < pdispparams->cNamedArgs; nIndex++)
    162.             pVarArgs[pdispparams->rgdispidNamedArgs[nIndex]] = &pdispparams->rgvarg[nIndex];
    163. #endif
    164.         for (; nIndex < pdispparams->cArgs; nIndex++)
    165.             pVarArgs[info.nParams-nIndex-1] = &pdispparams->rgvarg[nIndex];
    166.         CComStdCallThunk<T> thunk;
    167.         thunk.Init(pEvent, pT);
    168.         CComVariant tmpResult;
    169.         if (pvarResult == NULL)
    170.             pvarResult = &tmpResult;
    171.         HRESULT hr = DispCallFunc(
    172.             &thunk,
    173.             0,
    174.             info.cc,
    175.             info.vtReturn,
    176.             info.nParams,
    177.             info.pVarTypes,
    178.             pVarArgs,
    179.             pvarResult);
    180.         ATLASSERT(SUCCEEDED(hr));
    181.         return hr;
    182.     }
    183.     //Helper for finding the function index for a DISPID
    184.     virtual HRESULT GetFuncInfoFromId(const IID& /*iid*/, DISPID /*dispidMember*/LCID /*lcid*/, _ATL_FUNC_INFO& /*info*/)
    185.     {
    186.         ATLTRACE(_T("TODO: Classes using IDispEventSimpleImpl should override this method/n"));
    187.         ATLASSERT(0);
    188.         ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetFuncInfoFromId"));
    189.     }
    190.     //Helpers for sinking events on random IUnknown*
    191.     HRESULT DispBrowserEventAdvise(IUnknown* pUnk)
    192.     {
    193.         ATLENSURE(m_dwBrowserEventCookie == 0xFEFEFEFE);        
    194.         return AtlAdvise(pUnk, (IUnknown*)this,DIID_DWebBrowserEvents2, &m_dwBrowserEventCookie);
    195.     }
    196.     HRESULT DispBrowserEventUnadvise(IUnknown* pUnk)
    197.     {
    198.         HRESULT hr = AtlUnadvise(pUnk,DIID_DWebBrowserEvents2, m_dwBrowserEventCookie);
    199.         m_dwBrowserEventCookie = 0xFEFEFEFE;
    200.         return hr;
    201.     }
    202.     HRESULT DispDocumentEventAdvise(IUnknown* pUnk)
    203.     {
    204.         ATLENSURE(m_dwDocumentEventCookie == 0xFEFEFEFE);       
    205.         return AtlAdvise(pUnk, (IUnknown*)this, DIID_HTMLDocumentEvents2, &m_dwDocumentEventCookie);
    206.     }
    207.     HRESULT DispDocumentEventUnadvise(IUnknown* pUnk)
    208.     {
    209.         HRESULT hr = AtlUnadvise(pUnk,DIID_HTMLDocumentEvents2, m_dwDocumentEventCookie);
    210.         m_dwDocumentEventCookie = 0xFEFEFEFE;
    211.         return hr;
    212.     }
    213.     HRESULT DispElementEventAdvise(IUnknown* pUnk, const IID* piid,DWORD * dwCookie)
    214.     {       
    215.         ///ATLASSERT(*dwCookie == 0xFEFEFEFE);
    216.         return AtlAdvise(pUnk, (IUnknown*)this, *piid,dwCookie);
    217.     }
    218.     HRESULT DispElementEventUnadvise(IUnknown* pUnk, const IID* piid,DWORD * dwCookie)
    219.     {
    220.         HRESULT hr = AtlUnadvise(pUnk, *piid,*dwCookie);
    221.         *dwCookie = 0xFEFEFEFE;
    222.         return hr;
    223.     }
    224. };
    225. #define EASY_SINK_ENTRY(id,iid, dispid,fn,info) {id, &iid,0, dispid, (void (__stdcall _atl_event_classtype::*)())fn, info},
    EASY_SINK_ENTRY 是SINK_ENTRY_INFO的替代物,因为我们自定了_ATL_EVENT_ENTRY结构的pInfo成员,因此nOffset可以为了0了。使用方法:

  1. _ATL_FUNC_INFO DocumentComplete2Struct={CC_STDCALL, VT_EMPTY, 2, {VT_DISPATCH, VT_BYREF|VT_VARIANT}};
  2. //....
  3. _ATL_FUNC_INFO ClickEventStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_DISPATCH}};

  4. class CMyClass : public EasyDispEventImpl<1, CMyClass > 
  5. {
  6. public:
  7.     BEGIN_SINK_MAP(CMyClass)    
  8.         EASY_SINK_ENTRY(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, __DocumentComplete, &DocumentComplete2Struct)
  9.         EASY_SINK_ENTRY(1, DIID_HTMLDocumentEvents2, DISPID_HTMLELEMENTEVENTS2_ONCLICK, __Click, &ClickEventStruct)
  10.     END_SINK_MAP()
  11. void __stdcall __DocumentComplete(IDispatch* pDisp, VARIANT* pvURL)
  12.     {
  13.         //TODO...
  14.     }
  15.   void __stdcall __Click(IDispatch* pDisp)
  16.     {
  17.         T* pT = static_cast<T*>(this);
  18.         CComQIPtr<IHTMLEventObj2> evt(pDisp);
  19.                 //TODO .... 
  20.     }
  21. };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值