c++ - IE9 无法在 BHO 中的 HTMLWindow2 上触发 onscroll 事件

标签 c++ internet-explorer events bho

IE 可以在使用文档模式时触发 onscroll 事件:IE7 或 IE8,但fail在使用文档模式时触发 onscroll 事件:<强>IE9。我还在 documentElement 上注册了 onscroll 事件,它的 react 方式相同。

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

然后将其通知到Document Complete中的window对象:

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

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

我已经研究这个问题很长一段时间了。有任何想法吗?非常感谢!

最佳答案

对于 IE9 和文档模式 = IE9,您需要使用"new"事件。

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

关于c++ - IE9 无法在 BHO 中的 HTMLWindow2 上触发 onscroll 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8472829/

相关文章:

jquery - jQuery 中同时具有 mousedown/mouseup 和 dblclick

c++ - 如何将类中的函数放入线程中? (使用 Boost 的 C++)

c# - 是否可以捕获或隐藏非托管异常窗口?

javascript - IE 在 Canvas 上调用 toDataUrl 时抛出安全错误

jQuery 验证器 - 在 IE 中突出显示下拉列表

javascript - Internet Explorer 不写入 document.cookie?

linux - 无法让 eventfd 与 epoll 一起工作

android - 是否可以在同一个Textview上使用拖动事件和点击事件?

具有模板函数的嵌套命名空间中的 C++ ADL

c++ - 奇怪,双击/鼠标拖动会触发按键事件 "CTRL-C"