JS调用BHO

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

  

  

原文地址:https://www.cnblogs.com/dlbrant/p/3142887.html