2012-03-02 58 views
1

IE可以觸發onscroll事件中使用文檔模式時:IE7或IE8,但失敗使用文檔模式何時啓onscroll事件IE9。我還在documentElement上註冊了onscroll事件,它以同樣的方式作出反應。IE9未能開火HTMLWindow2 onscroll事件在BHO

的BHO類使用:

public IDispEventImpl<3, CHelloWorldBHO, &DIID_HTMLWindowEvents2, &LIBID_MSHTML, 4, 0>. 

和水槽事件:

BEGIN_SINK_MAP(CHelloWorldBHO) 
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete) 
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_NAVIGATECOMPLETE2, OnNavigateComplete2) 
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_WINDOWSTATECHANGED, OnWindowStateChanged) 
SINK_ENTRY_EX(3, DIID_HTMLWindowEvents2, DISPID_HTMLWINDOWEVENTS2_ONSCROLL, OnScroll) 
END_SINK_MAP() 

然後勸到窗口對象文檔完整

CComQIPtr<IHTMLDocument2> spHTMLDoc = spDispDoc; 
CComQIPtr<IHTMLWindow2> spTempWindow2; 
spHTMLDoc->get_parentWindow(&spTempWindow2); 

IDispEventImpl<3, CHelloWorldBHO, &DIID_HTMLWindowEvents2, &LIBID_MSHTML, 4, 0>::DispEventAdvise(spTempWindow2); 

我有一直在研究這個問題。有任何想法嗎?非常感謝!

回答

4

使用IE9和文檔模式= IE9,您需要使用「新」事件。

hr = _spDocument->get_parentWindow(reinterpret_cast<IHTMLWindow2 **>(&_spWindow)); 
if (SUCCEEDED(hr) && _spWindow) 
{ 
    // If document mode is lower than 9 we can had the OnScrollEvent the old way 
    if(_uiDocumentMode < 9) 
    { 
     hr = IDispEventImpl<2, CIEPage, &DIID_HTMLWindowEvents2, &LIBID_MSHTML, 4, 0>::DispEventAdvise(_spWindow);      
     if(SUCCEEDED(hr)) 
     { 
      ... 
     } 
    } 
    else 
    { 
     CComPtr<IEventTarget> spIEventTarget; 
     hr = _spWindow->QueryInterface(IID_IEventTarget, reinterpret_cast<void **>(&spIEventTarget)); 
     if (SUCCEEDED(hr) && spIEventTarget) 
     { 
      _spEventScroll = new CIE9UIEvent(); // This class must derive from IDispatchEx 

      CComPtr<IDispatch> spIDispatch; 
      HRESULT hr = _spEventScroll->QueryInterface(IID_IDispatch, reinterpret_cast<void **>(&spIDispatch)); // Get the IDispatch 
      if (SUCCEEDED(hr) && spIDispatch) 
      { 
       // If _spEventScroll is used instead of spIDispatch, an exception will occurr!!! 
       hr = _spIEventTarget->addEventListener(_bstr_t("scroll"), spIDispatch, VARIANT_TRUE); 
       if (SUCCEEDED(hr)) 
       { 
        ... 
       } 
      } 
     } 
    } 
} 

現在在你的派生類...

////////////////////////////////////////////////////////////////////// 
// InvokeEx 
////////////////////////////////////////////////////////////////////// 
HRESULT STDMETHODCALLTYPE CIE9UIEvent::InvokeEx(    
      __in DISPID dispIdMember,    
      __in LCID lcid,    
      __in WORD wFlags,    
      __in DISPPARAMS* pDispParams,    
      __out_opt VARIANT *pvarRes,    
      __out_opt EXCEPINFO *pei,    
      __in_opt IServiceProvider *pspCaller) 
{ 
    if(dispIdMember == 0 && pDispParams->cArgs == 2) 
    { 
     if(pDispParams->rgvarg[1].vt == VT_DISPATCH && pDispParams->rgvarg[1].pdispVal) 
     { 
      CComPtr<IDOMEvent> spIDOMEvent; 
      HRESULT hr = pDispParams->rgvarg[1].pdispVal->QueryInterface(IID_IDOMEvent, reinterpret_cast<void **>(&spIDOMEvent)); 
      if(SUCCEEDED(hr) && spIDOMEvent) 
      { 
       ... 
      } 
     } 
    } 

    return S_OK; 
} 

最後一步是在你的類QueryInterface方法添加IDispatchEx

////////////////////////////////////////////////////////////////////// 
// QueryInterface 
////////////////////////////////////////////////////////////////////// 
HRESULT STDMETHODCALLTYPE CIE9EventListener::QueryInterface(REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) 
{ 
    *ppvObject = NULL; 
    if(IsEqualGUID(riid, IID_IUnknown)) 
     *ppvObject = reinterpret_cast<void**>(this); 

    if(IsEqualGUID(riid, IID_IDispatch)) 
     *ppvObject = reinterpret_cast<void**>(this); 

    if(IsEqualGUID(riid, IID_IDispatchEx)) 
     *ppvObject = reinterpret_cast<void**>(this); 


    if(*ppvObject) 
    { 
     ((IUnknown*)*ppvObject)->AddRef(); 
     return S_OK; 
    } 

    return E_NOINTERFACE; 
}