其实是抄的别人的代码。我改了改而已。
IOleClientSite在ATL和MFC的控件类里都可以拿得到。没任何问题。
#pragma once
#include <atlbase.h>
#include <SHLGUID.h>
#include <Mshtml.h>
#include <vector>
#include <string>
#include <comdef.h>
class CJsInvoker
{
public:
CJsInvoker();
BOOL CallJsFunction(const BSTR strJSFuncName, std::vector<std::wstring> vCallArgs);
BOOL Init(IOleClientSite* pClientSite);
protected:
IOleClientSite* m_pClientSite; //
IWebBrowser2* m_spBrowser; //
IHTMLDocument2* m_spDoc; //
};
--------------------------无耻的分割线-----------------------------------------------
#include "stdafx.h"
#include "JSInvoker.h"
BSTR Copy(const wchar_t* str) throw()
{
if (str == NULL)
{
return NULL;
}
return ::SysAllocStringByteLen((char*)str, (wcslen(str) + 1) * sizeof(wchar_t) );
}
// copy BSTR to VARIANT
_Check_return_ HRESULT CopyTo(const wchar_t* str , _Out_opt_ VARIANT *pvarDest) throw()
{
ATLASSERT(pvarDest != NULL);
HRESULT hRes = E_POINTER;
if (pvarDest != NULL)
{
pvarDest->vt = VT_BSTR;
pvarDest->bstrVal = Copy(str);
#pragma warning(push)
#pragma warning(disable:4068)
#pragma prefast(push)
#pragma prefast(disable:325, "We are checking allocation semantics here")
if (pvarDest->bstrVal == NULL && str != NULL)
{
hRes = E_OUTOFMEMORY;
}
#pragma prefast(pop)
#pragma warning(pop)
else
{
hRes = S_OK;
}
}
return hRes;
}
BOOL CJsInvoker::CallJsFunction(const BSTR strJSFuncName , std::vector<std::wstring> vCallArgs)
{
HRESULT hr = S_OK;
try
{
//
CComPtr<IDispatch> pScript;
hr = m_spDoc->get_Script(&pScript);
//
CComBSTR bstrMember(strJSFuncName);
DISPID dispid;
hr = pScript->GetIDsOfNames(::IID_NULL, &bstrMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
//
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = vCallArgs.size();
dispparams.rgvarg = new VARIANT[dispparams.cArgs];
for(size_t i = 0; i < vCallArgs.size(); i++)
{
CopyTo(vCallArgs[i].c_str() , &dispparams.rgvarg[i]);
dispparams.rgvarg[i].vt = VT_BSTR;
}
//
dispparams.cNamedArgs = 0;
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof excepInfo);
CComVariant vaResult;
UINT nArgErr = (UINT)-1; //initialize to invalid arg
hr = pScript->Invoke(dispid, ::IID_NULL, 0, DISPATCH_METHOD, &dispparams, &vaResult, &excepInfo, &nArgErr);
for(size_t i = 0; i < vCallArgs.size(); i++)
{
::SysFreeString(dispparams.rgvarg[i].bstrVal);
}
delete [] dispparams.rgvarg;
}
catch(...)
{
return FALSE;
}
return (hr == S_OK ? TRUE : FALSE);
}
CJsInvoker::CJsInvoker()
{
m_pClientSite = NULL;
m_spBrowser = NULL;
m_spDoc = NULL;
}
BOOL CJsInvoker::Init(IOleClientSite* pClientSite)
{
m_pClientSite = pClientSite;
HRESULT hr = S_OK;
::IServiceProvider* isp = NULL;
::IServiceProvider* isp2 = NULL;
try
{
if (m_pClientSite == NULL)
{
return FALSE;
}
hr = m_pClientSite->QueryInterface(::IID_IServiceProvider, reinterpret_cast<void **>(&isp));
if( FAILED(hr) )
{
return FALSE;
}
hr = isp->QueryService(::SID_STopLevelBrowser, ::IID_IServiceProvider, reinterpret_cast<void **>(&isp2));
if( FAILED(hr) )
{
return FALSE;
}
hr = isp2->QueryService(::SID_SWebBrowserApp, ::IID_IWebBrowser2, reinterpret_cast<void **>(&m_spBrowser));
if( FAILED(hr) )
{
return FALSE;
}
//
if(m_spDoc != NULL)
{
delete m_spDoc;
m_spDoc = NULL;
}
hr = m_spBrowser->get_Document((IDispatch**)&m_spDoc);
if( FAILED(hr) )
{
return FALSE;
}
return TRUE;
}
catch(...)
{
return FALSE;
}
}