1

我正在使用 VS2008、C++ 创建一个浏览器助手对象。我的课程是从 IDispEventImpl 等派生的

class ATL_NO_VTABLE CHelloWorldBHO :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CHelloWorldBHO, &CLSID_HelloWorldBHO>,
    public IObjectWithSiteImpl<CHelloWorldBHO>,
    public IDispatchImpl<IHelloWorldBHO, &IID_IHelloWorldBHO, &LIBID_HelloWorldLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
    public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>

{
.
.
.
BEGIN_SINK_MAP(CHelloWorldBHO)
     SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
     SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_BEFORENAVIGATE2, BeforeNavigate2)//Handle BeforeNavigate2
END_SINK_MAP()
.
.
.
}

从上面的代码可以看出,我的 DWebBrowserEvents2 是使用 ATL 的宏处理的。现在我想处理 HTMLElementEvents2(以检测点击、滚动条等)。为此,我查询 IHTMLElement 的 IHTMLDocument2 对象,查询 IConnectionPointContainer 的 QueryInterface() 并调用 IConnectionPointContainer::FindConnectionPoint(DIID_HTMLElementEvents2)。(请参阅msdn关于处理 HTMLElementEvents2 的文章)。问题是,当我在我的类中覆盖 IDispatch::Invoke 时,DWebBrowserEvents2 句柄(使用 ATL 宏创建)失败。有没有办法在不覆盖 Invoke 的情况下处理 HTMLElementEvents2,或者以只处理 HTMLElementEvents2 的方式实现调用?
谢谢,任何帮助将不胜感激。

4

1 回答 1

1

没有真正需要重写 Invoke 或获取 IConnectionPointContainer。由于这是一个 ATL 项目,实现另一个 IDispEventImpl:

public IDispEventImpl<2, CHelloWorldBHO, &DIID_HTMLTextContainerEvents2, &LIBID_MSHTML, 4, 0>

成功了。然后,将条目下沉为:

SINK_ENTRY_EX(2, DIID_HTMLTextContainerEvents2, DISPID_ONSCROLL, OnScroll)

在 OnDocumentComplete 中,调用 IWebBrowser2::get_Document、IHTMLDocument2::get_body,然后调用 DispEventAdvise 开始接收事件。

请注意,我使用的是 DIID_HTMLTextContainerEvents2 而不是 DIID_HTMLElementEvents。那是因为 body 对象不支持 HTMLElementEvents2,并且出于我的目的(处理滚动),它工作得很好!

于 2009-07-17T20:34:11.823 回答