将对象与 IDispatch 进行比较以仅获取主框架(BHO)

发布于 2024-08-24 04:48:11 字数 1728 浏览 3 评论 0原文

我不知道是否有人熟悉 BHO(浏览器帮助对象),但 c++ 专家也可以帮助我。

在我的 BHO 中,我只想在主框架(第一个容器)上运行 OnDocumentComplete() 函数,而不是在当前页面内的所有 Iframe 上运行。 (另一种方法是仅当这是主框架时才放置一些代码)。

我找不到如何跟踪何时填充主框架。

在谷歌搜索后,我发现每个帧都有“IDispatch* pDisp”,我必须将它与指向第一个帧的指针进行比较。

这是主要功能:

STDMETHODIMP Browsarity::SetSite(IUnknown* pUnkSite)
{
    if (pUnkSite != NULL)
    {
        // Cache the pointer to IWebBrowser2.
        HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
        if (SUCCEEDED(hr))
        {
            // Register to sink events from DWebBrowserEvents2.
            hr = DispEventAdvise(m_spWebBrowser);
            if (SUCCEEDED(hr))
            {
                m_fAdvised = TRUE;
            }
        }
    }
    else
    {
        // Unregister event sink.
        if (m_fAdvised)
        {
            DispEventUnadvise(m_spWebBrowser);
            m_fAdvised = FALSE;
        }

        // Release cached pointers and other resources here.
        m_spWebBrowser.Release();
    }

    // Call base class implementation.
    return IObjectWithSiteImpl<Browsarity>::SetSite(pUnkSite);
}

这是我想知道它是否是主窗口(框架)的地方:

void STDMETHODCALLTYPE Browsarity::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
  // as you can see, this function get the IDispatch *pDisp which is unique to every frame.
  //some code
}

我在微软论坛上问了这个问题,我得到了答案,但没有解释如何实际实现:http://social.msdn.microsoft.com /Forums/zh-CN/ieextensiondevelopment/thread/7c433bfa-30d7-42db-980a-70e62640184c

I don't know if anyone familiar with BHO (Browser Helper Object), but an expert in c++ can help me too.

In my BHO I want to run the OnDocumentComplete() function only on the main frame - the first container and not all the Iframes inside the current page. (an alternative is to put some code only when this is the main frame).

I can't find how to track when is it the main frame that being populated.

After searching in google I found out that each frame has "IDispatch* pDisp", and I have to compare it with a pointer to the first one.

This is the main function:

STDMETHODIMP Browsarity::SetSite(IUnknown* pUnkSite)
{
    if (pUnkSite != NULL)
    {
        // Cache the pointer to IWebBrowser2.
        HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
        if (SUCCEEDED(hr))
        {
            // Register to sink events from DWebBrowserEvents2.
            hr = DispEventAdvise(m_spWebBrowser);
            if (SUCCEEDED(hr))
            {
                m_fAdvised = TRUE;
            }
        }
    }
    else
    {
        // Unregister event sink.
        if (m_fAdvised)
        {
            DispEventUnadvise(m_spWebBrowser);
            m_fAdvised = FALSE;
        }

        // Release cached pointers and other resources here.
        m_spWebBrowser.Release();
    }

    // Call base class implementation.
    return IObjectWithSiteImpl<Browsarity>::SetSite(pUnkSite);
}

This is where I want to be aware whether its the main window(frame) or not:

void STDMETHODCALLTYPE Browsarity::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
  // as you can see, this function get the IDispatch *pDisp which is unique to every frame.
  //some code
}

I asked this question on Microsoft forum and I got an answer without explaining how to actually implement that: http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/7c433bfa-30d7-42db-980a-70e62640184c

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深爱不及久伴 2024-08-31 04:48:11

jeffdav建议的是,通过QueryInterface()测试pDisp是否支持IWebBrowser2,如果支持,检查它是否是同一个对象作为您存储在 SetSite() 中的那个。
QueryInterface() 规则< /a> 仅要求 IUnknownQI 始终产生相同的指针值,因此您必须将 QI 附加到 IUnknown 并比较结果指针。

这会导致 OnDocumentComplete() 中出现类似的情况:

IWebBrowser2* pBrowser = 0;
IUnknown *pUnk1=0, *pUnk2=0;
if(   SUCCEEDED(pDisp      ->QueryInterface(IID_IWebBrowser2, (void**)&pBrowser))
   && SUCCEEDED(pDisp      ->QueryInterface(IID_IUnknown,     (void**)&pUnk1))
   && SUCCEEDED(m_spBrowser->QueryInterface(IID_IUnknown,     (void**)&pUnk2))
   && (pUnk1 == pUnk2)) 
{
    // ... top-level
}

...或者如果您使用 ATL(如 m_spWebBrowser 建议):

CComQIPtr<IWebBrowser2> spBrowser(pDisp);
if(spBrowser && spBrowser.IsEqualObject(m_spWebBrowser)) {
    // ...
}

What jeffdav suggested is, to test wether the pDisp supports IWebBrowser2 via QueryInterface(), and if so, to check wether it is the same object as the one you stored in SetSite().
The QueryInterface() rules only require that a QI for IUnknown always results in the same pointer value, so you have to additionally QI to IUnknown and compare the resulting pointers.

This would lead to something like this in OnDocumentComplete():

IWebBrowser2* pBrowser = 0;
IUnknown *pUnk1=0, *pUnk2=0;
if(   SUCCEEDED(pDisp      ->QueryInterface(IID_IWebBrowser2, (void**)&pBrowser))
   && SUCCEEDED(pDisp      ->QueryInterface(IID_IUnknown,     (void**)&pUnk1))
   && SUCCEEDED(m_spBrowser->QueryInterface(IID_IUnknown,     (void**)&pUnk2))
   && (pUnk1 == pUnk2)) 
{
    // ... top-level
}

... or if you are using ATL (as m_spWebBrowser suggests):

CComQIPtr<IWebBrowser2> spBrowser(pDisp);
if(spBrowser && spBrowser.IsEqualObject(m_spWebBrowser)) {
    // ...
}
千柳 2024-08-31 04:48:11

请注意,我没有对此进行测试,我只是重写了 msdn 上的人所说的内容。

在 ::SetSite 中你得到一个 IUnknown 指针。对其调用 IUnknown::QueryInterface(就像您已经在做的那样),但使用 IID_IDISPATCH。把这个指针保存在某个地方,这个指针就是顶层框架。

在 ::OnDocumentComplete 中,您将获得一个 IDispatch 指针,将其与之前保存的 ptr 进行比较,瞧,如果存在匹配项,则您位于顶层。

Notice that I did not test this, I'm only rewriting what the guy on msdn said.

In ::SetSite you get an IUnknown pointer. Call IUnknown::QueryInterface on it (just like you're already doing), but instead use IID_IDISPATCH. Save this pointer somewhere, this pointer is the top level frame.

In ::OnDocumentComplete you're getting a IDispatch pointer, compare this one to the previous saved ptr and voíla, if there is a match you're in the top level.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文