我正在为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);
}
}
答案 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);