我的BHO无法正常工作。 DocumentComplete不会触发

时间:2010-08-26 06:15:54

标签: visual-c++ bho

我正在为Internet Explorer做BHO。问题是只有SetSite正在运行。 BUt DocumentComplete未被触发。我需要一些帮助来指出我做错了什么。

这是我在头文件中声明的内容:

class ATL_NO_VTABLE CStockBar : 
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CStockBar, &CLSID_StockBar>,
public IDeskBand,
public IObjectWithSite,
public IObjectWithSiteImpl<CStockBar>,
public IInputObject, 
public IDispatchImpl<IStockBar, &IID_IStockBar, &LIBID_MOTLEYFOOLLib>,
public IDispEventImpl<1, CStockBar, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
{
public:
CStockBar();

DECLARE_REGISTRY_RESOURCEID(IDR_STOCKBAR)
DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_CATEGORY_MAP(CStockBar)
//  IMPLEMENTED_CATEGORY(CATID_InfoBand)
//  IMPLEMENTED_CATEGORY(CATID_CommBand)
//  IMPLEMENTED_CATEGORY(CATID_DeskBand)
END_CATEGORY_MAP()

BEGIN_COM_MAP(CStockBar)
COM_INTERFACE_ENTRY(IStockBar)
//  COM_INTERFACE_ENTRY(IInputObject)
COM_INTERFACE_ENTRY(IOleWindow)
COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
COM_INTERFACE_ENTRY(IObjectWithSite)
COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

BEGIN_SINK_MAP(CStockBar)
    SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()

这是我的SetSite和DocumentComplete函数:

   STDMETHODIMP CStockBar::SetSite(IUnknown* pUnkSite)
   {
    //If a site is being held, release it.
if(m_pSite)
{
    m_ReflectWnd.GetToolBar().SetBrowser(NULL);
    m_pSite->Release();
    m_pSite = NULL;
}
    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
{
  if (m_fAdvised)
    {
        DispEventUnadvise(m_spWebBrowser);
        m_fAdvised = FALSE;
    }
    m_spWebBrowser.Release();
}
//If punkSite is not NULL, a new site is being set.
if(pUnkSite)
{
    //Get the parent window.
    IOleWindow  *pOleWindow = NULL;

    m_hWndParent = NULL;

    if(SUCCEEDED(pUnkSite->QueryInterface(IID_IOleWindow, (LPVOID*)&pOleWindow)))
    {
        pOleWindow->GetWindow(&m_hWndParent);
        pOleWindow->Release();
    }

    if(!::IsWindow(m_hWndParent))
        return E_FAIL;

    if(!RegisterAndCreateWindow())
        return E_FAIL;

    //Get and keep the IInputObjectSite pointer.
    if(FAILED(pUnkSite->QueryInterface(IID_IInputObjectSite, (LPVOID*)&m_pSite)))
    {
        return E_FAIL;
    }  

    IWebBrowser2* s_pFrameWB = NULL;
    IOleCommandTarget* pCmdTarget = NULL;
    HRESULT hr = pUnkSite->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&pCmdTarget);
    if (SUCCEEDED(hr))
    {
        IServiceProvider* pSP;
        hr = pCmdTarget->QueryInterface(IID_IServiceProvider, (LPVOID*)&pSP);

        pCmdTarget->Release();

        if (SUCCEEDED(hr))
        {
            hr = pSP->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID*)&s_pFrameWB);
            pSP->Release();
            _ASSERT(s_pFrameWB);
            m_ReflectWnd.GetToolBar().SetBrowser(s_pFrameWB);
            s_pFrameWB->Release();
        }
    }
 }
return S_OK;
   }




  void STDMETHODCALLTYPE CStockBar::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
 {
   // Retrieve the top-level window from the site.
   HWND hwnd;
   HRESULT hr = m_spWebBrowser->get_HWND((LONG_PTR*)&hwnd);
   if (SUCCEEDED(hr))
  {
    // Output a message box when page is loaded.
    MessageBox(hwnd,"Hello World!","BHO", MB_OK);
  }
 }

2 个答案:

答案 0 :(得分:0)

您应该将SINK_ENTRY_INFO与IDispEventImpl一起使用 http://msdn.microsoft.com/en-us/library/2wt7d0s4(v=vs.80).aspx

你可能正在发布你的代码,否则你会得到一个断言,因为idispeventimpl将无法检索DIID_DWebBrowserEvents2的类型库。 DIID_DWebBrowserEvents2没有typelib,因为它是一个disp接口。

在标题中声明:

extern ATL::_ATL_FUNC_INFO DocumentComplete2Struct;

BEGIN_SINK_MAP(CStockBar)
    SINK_ENTRY_INFO(1, __uuidof(DWebBrowserEvents2), DISPID_DOCUMENTCOMPLETE, OnDocumentComplete, &DocumentComplete2Struct);
END_SINK_MAP()

在您的CPP中:

ATL::_ATL_FUNC_INFO DocumentComplete2Struct = {CC_STDCALL, VT_EMPTY, 2, {VT_DISPATCH, VT_BYREF|VT_VARIANT}};

答案 1 :(得分:0)

我无法看到任何突出显示不正确的内容,所以这里有另一个例子,其中包含一些工作代码,只包含网站所需的位以保持简单。

可能存在的一个问题是 - m_spWebBrowser如果这是ATL类,那么它不喜欢你使用设置后的地址覆盖现有的。它可能会返回false,此时您将不会运行建议。     HRESULT hr = pUnkSite-&gt; QueryInterface(IID_IWebBrowser2,(void **)&amp; m_spWebBrowser);

声明h

class ATL_NO_VTABLE CStockBar: 
    public CComObjectRootEx<CComGlobalsThreadModel>,
    public CComCoClass<CStockBar, &CLSID_StockBar>, 
    public IObjectWithSiteImpl<CStockBar>,
    public IDispEventImpl<1, CStockBar, &__uuidof(DWebBrowserEvents2), &LIBID_SHDocVw, 1, 0>{

protected:
    typedef IDispEventImpl<1, CStockBar, &__uuidof(DWebBrowserEvents2), &LIBID_SHDocVw, 1, 0> base_BrowserDispEvents;
    typedef IObjectWithSiteImpl<CStockBar> base_objectWithSite;

BEGIN_SINK_MAP(CStockBar)
// we use this variation - think it resolves the same
    SINK_ENTRY_EX(1, (__uuidof(DWebBrowserEvents2)), DISPID_DOCUMENTCOMPLETE, OnDocumentComplete) 
    SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()

CComQIPtr<IWebBrowser2> m_spBrowser;

实施cpp

STDMETHODIMP CStockBar::SetSite(IUnknown* pUnkSite) {

    // Detach the web browser and site
    if (m_spBrowser) {
        base_BrowserDispEvents::DispEventUnadvise(m_spBrowser);
        m_spBrowser.Release();
    }

    if (pUnkSite) {

        m_spBrowser = pUnkSite;
        if (m_spBrowser)
        {
            base_BrowserDispEvents::DispEventAdvise(m_spBrowser);
        }

    }

    return base_objectWithSite::SetSite(pUnkSite);