// 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; }