2010-08-26 52 views
1

我正在爲Internet Explorer做一個BHO。問題是隻有SetSite正在工作。 BUMP DocumentComplete沒有被觸發。我需要一些幫助來指導我做錯了什麼。我的BHO無法正常工作。 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); 
    } 
} 

回答

0

你應該IDispEventImpl的使用SINK_ENTRY_INFO作爲 http://msdn.microsoft.com/en-us/library/2wt7d0s4(v=vs.80).aspx

指出

你可能正在運行你的代碼,否則你會得到一個斷言,因爲idispev entimpl將無法檢索DIID_DWebBrowserEvents2的typelib。 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}}; 
0

我看不到任何東西,凸現出definably不正確,所以這裏是黑客入侵了一些工作的另一個例子代碼,僅包含網站所需的位以保持簡單。

可能是一個問題的一件事是 - 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);