Мой BHO не работает должным образом.DocumentComplete не запускается - PullRequest
1 голос
/ 26 августа 2010

Я делаю BHO для Internet Explorer.Проблема только в том, что 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 голосов
/ 19 августа 2011

Я не вижу ничего, что выделяется как явно некорректное, поэтому вот еще один пример, взломанный из некоторого рабочего кода, включающий только биты, необходимые для сайта, чтобы сделать его простым.

Одна вещь, которая можетбыть проблемой - m_spWebBrowser если это класс ATL, то вам не нравится, когда вы перезаписываете существующий, используя адрес после его установки.Возможно, он возвращает false, и в этот момент вы не будете давать советы.HRESULT hr = pUnkSite-> QueryInterface (IID_IWebBrowser2, (void **) & 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);
0 голосов
/ 05 февраля 2011

Вы должны использовать SINK_ENTRY_INFO с IDispEventImpl, как указано в http://msdn.microsoft.com/en-us/library/2wt7d0s4(v=vs.80).aspx

Вы, вероятно, запускаете свой код в выпуске, так как в противном случае вы бы получили утверждение, потому что idispeventimpl не смог бы получить библиотеку типов для DIID_DWebBrowserEvents2,DIID_DWebBrowserEvents2 не имеет библиотеки типов, потому что это интерфейс 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}};
...