// BHO 中添加下面的函数,设置UIHandler
// BHO 包含如下成员变量:
// CDocDispatch m_docDispatch;
// CComPtr<IDocHostUIHandler> m_spDefaultDocHostUIHandler;
// CComPtr<IOleCommandTarget> m_spDefaultOleCommandTarget;
HRESULT CBHO::SetDocHostUIHandler(IDispatch *pWebBrowser) { HRESULT hr = S_OK; if(NULL == pWebBrowser){ hr = S_FALSE; } else{ CComQIPtr<IWebBrowser2> spTempWebBrowser = pWebBrowser; // only deal with the main window if (spTempWebBrowser && m_spWebBrowser && m_spWebBrowser.IsEqualObject(spTempWebBrowser)) { CComPtr<IDispatch> spDispDoc = NULL; hr = spTempWebBrowser->get_Document(&spDispDoc); if (SUCCEEDED(hr) && NULL != spDispDoc) { CComQIPtr<IHTMLDocument2> spDoc2 = spDispDoc; if (spDoc2) { // Request default handler from MSHTML client site CComQIPtr<IOleObject> spOleObject = spDispDoc; if (spOleObject) { CComPtr<IOleClientSite> spClientSite = NULL; hr = spOleObject->GetClientSite(&spClientSite); if (SUCCEEDED(hr) && spClientSite) { m_spDefaultDocHostUIHandler = spClientSite; m_spDefaultOleCommandTarget = spClientSite; } } // Set the new custom IDocHostUIHandler CComQIPtr<ICustomDoc> spCustomDoc = spDoc2; if (spCustomDoc) { hr = spCustomDoc->SetUIHandler(this); } } } } } return hr; }
在CBHO::Invoke中调用上面的函数
... ...
switch (dispidMember)
{
case DISPID_NAVIGATECOMPLETE2:
{
IDispatch* pDisp = pDispParams->rgvarg[1].pdispVal;
SetDocHostUIHandler(pDisp);
}
break;
}
... ...
CBHO实现IID_IDocHostUIHandler::GetExternal接口
HRESULT STDMETHODCALLTYPE CBHO::GetExternal(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
{
*ppDispatch = (IDispatch*)(&m_docDispatch);
return S_OK;
}
CBHO::SetSite中设置m_docDispatch
STDMETHODIMP CBHO::SetSite(IUnknown* pUnkSite)
{
if (pUnkSite != NULL)
{
pUnkSite->QueryInterface(IID_IWebBrowser2, (void**)&m_spWebBrowser);
if (m_spWebBrowser)
{
m_docDispatch.SetSite(this);
... ...
}
}
else
{
m_docDispatch.SetSite(NULL);
... ...
}
... ...
return IObjectWithSiteImpl<CBHOMain>::SetSite(pUnkSite);
}
实现CDocDispatch::GetIDsOfNames
HRESULT STDMETHODCALLTYPE CDocDispatch::GetIDsOfNames(
REFIID riid,
LPOLESTR __RPC_FAR *rgszNames,
UINT cNames,
LCID lcid,
DISPID __RPC_FAR *rgDispId)
{
UNREFERENCED_PARAMETER(riid);
UNREFERENCED_PARAMETER(lcid);
HRESULT hr = S_OK;
for (UINT i=0; i < cNames; i++)
{
CComBSTR bsName = rgszNames[i];
if (0 == _tcsicmp(bsName, _T("Func1")))
{
rgDispId[i] = ID_OF_FUNC1;
}
else if(0 == _tcsicmp(bsName, _T("Func2")))
{
rgDispId[i] = ID_OF_FUNC2;
}
else
{
// One or more are unknown so set the return code accordingly
hr = ResultFromScode(DISP_E_UNKNOWNNAME);
rgDispId[i] = DISPID_UNKNOWN;
hr = E_NOTIMPL;
}
}
... ...
return hr;
}
实现CDocDispatch::Invoke
HRESULT STDMETHODCALLTYPE CDocDispatch::Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS __RPC_FAR *pDispParams,
VARIANT __RPC_FAR *pvarResult,
EXCEPINFO __RPC_FAR *pexcepinfo,
UINT __RPC_FAR *puArgErr)
{
HRESULT hr = S_OK;
switch(dispIdMember)
{
case ID_OF_FUNC1:
if(m_pSite)
{
// 如果调用其他js函数,需要注意参数顺序
m_pSite->CallToJsFunction(pDispParams->rgvarg[1].bstrVal, pDispParams->rgvarg[0].bstrVal);
}
break;
case ID_OF_FUNC2:
if(m_pSite)
{
// 设置返回值
long result = ...
CComVariant varResult(result );
hr = varResult.Detach(pvarResult);
}
break;
default:
break;
}
... ...
return hr;
}