IE9无法在BHO中的HTMLWindow2上触发onscroll事件 [英] IE9 fails to fire onscroll event on HTMLWindow2 in BHO

查看:450
本文介绍了IE9无法在BHO中的HTMLWindow2上触发onscroll事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

IE7或IE8,但失败 onscroll事件当使用文档模式:

IE浏览器可以使用的文件模式当火灾onscroll事件 IE9 。我也在documentElement上注册onscroll事件,它的反应方式相同。



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);

我一直在这个问题上工作了一段时间。有任何想法吗?非常感谢!

解决方案

使用IE9和文档模式= IE9,你需要使用

  hr = _spDocument-> get_parentWindow(reinterpret_cast< IHTMLWindow2 **>(& _spWindow)); 
如果(成功(HR)及和放大器; _spWindow)
{
//如果文档模式比9,我们可以有OnScrollEvent的老路上
如果(_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(); //此类必须从IDispatchEx派生

CComPtr< IDispatch> spIDispatch;
HRESULT hr = _spEventScroll-> QueryInterface(IID_IDispatch,reinterpret_cast< void **>(& spIDispatch)); //获取IDispatch的
如果(成功(HR)及和放大器; spIDispatch)
{
//如果_spEventScroll来代替spIDispatch的,破例将occurr!
hr = _spIEventTarget-> addEventListener(_bstr_t(scroll),spIDispatch,VARIANT_TRUE);
如果(成功(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)
{如果
(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)
{
...
}
}
}
$ b b 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;
}


IE can fire onscroll event when using Document Mode: IE7 or IE8, but fail to fire onscroll event when using Document Mode: IE9. I also register the onscroll event on documentElement, it reacts the same way.

The BHO class uses:

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

And sink the event:

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()

Then Advise it to the window object in Document Complete:

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

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

I have been working on this problem for quite a while. Any ideas? Thanks so much!

解决方案

With IE9 and document mode = IE9 you need to use the "new" Events.

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))
                {
                    ...
                }
            }
        }
    }
}

Now on your derived class...

//////////////////////////////////////////////////////////////////////
// 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;
}

Last step is to add in your class QueryInterface method the 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;
}

这篇关于IE9无法在BHO中的HTMLWindow2上触发onscroll事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆