从 C++ 调用 JavaScript






4.90/5 (57投票s)
一个用于从 C++ 代码轻松实现 JavaScript 调用的类。
引言
有时在使用 C++ 应用程序中的 IE 浏览器控件时,你需要访问 HTML 元素。我们可以使用标准的 COM 对象,如 IWebBrowser2
、IHTMLDocument2
等来实现。通过这种方法,我们可以轻松实现诸如点击按钮、点击锚点、获取输入字符串、获取 HTML 文本等功能。不幸的是,微软没有为 JavaScript 提供类似的接口。无论如何,通过传统的 COM 方法,控制 HTML 页面中的 JavaScript 对象是可行的。本文描述了类 CWebPage
,它允许这样做,以及从 C++ 代码调用 JavaScript 函数的技术。
如何操作
使用提供的类后,将可以轻松地从 C++ 代码调用任何 JavaScript 函数。为了实现此功能,我们应该获取指向 IHTMLDocument2
接口的指针。如果我们在 MFC 中使用 CHtmlView
类,可以使用成员函数 CHtmlView::GetHtmlDocument()
来获取它。在使用 IWebBrowser
或 IWebBrowser2
组件的情况下,函数 get_Document
将为我们带来所需的接口。这是一个例子:
CComPtr<IDispatch> spDisp = CHtmlView::GetHtmlDocument();
m_webPage.SetDocument(spDisp);
剩下的事情将由 CWebPage
类完成。这是一个不带参数的 JavaScript 调用的例子:
m_webPage.CallJScript("Welcome");
带有两个参数的 JavaScript 调用的例子如下所示:
m_webPage.CallJScript("Miltiply","2.34","3.32");
类的实现
class CWebPage
{
public:
CWebPage();
virtual ~CWebPage();
bool SetDocument(IDispatch* pDisp);
LPDISPATCH GetHtmlDocument() const;
const CString GetLastError() const;
bool GetJScript(CComPtr<IDispatch>& spDisp);
bool GetJScripts(CComPtr<IHTMLElementCollection>& spColl);
CString ScanJScript(CString& strAText,CStringArray& args);
bool CallJScript(const CString strFunc);
bool CallJScript(const CString strFunc,const CString strArg1);
bool CallJScript(const CString strFunc,const CString strArg1,
const CString strArg2);
bool CallJScript(const CString strFunc,const CString strArg1,
const CString strArg2,const CString strArg3);
bool CallJScript(const CString strFunc,const CStringArray& paramArray);
protected:
CComPtr<IHTMLDocument2> m_spDoc;
};
调用技术
上述技术可以分解为以下步骤:
- 获取指向
IHTMLDocument2
接口的指针。 - 获取 HTML 文档中 JavaScript 对象的
IDispatch
。 - 获取 JavaScript 函数给定名称的
DISPID
。 - 将参数放入
DISPPARAM
结构中。 - 使用
IDispatch
接口的Invoke
方法调用 JavaScript 函数。
这是一个获取 JavaScript 对象 IDispatch
指针的例子:
bool CWebPage::GetJScript(CComPtr<IDispatch>& spDisp)
{
HRESULT hr = m_spDoc->get_Script(&spDisp);
ATLASSERT(SUCCEEDED(hr));
return SUCCEEDED(hr);
}
这是调用 JavaScript 的最终函数:
CComVariant CWebPage::CallJScript(const CString strFunc,
const CStringArray& paramArray)
{
//Getting IDispatch for Java Script objects
CComPtr<IDispatch> spScript;
if(!GetJScript(spScript))
{
ShowError("Cannot GetScript");
return false;
}
//Find dispid for given function in the object
CComBSTR bstrMember(strFunc);
DISPID dispid = NULL;
HRESULT hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,
LOCALE_SYSTEM_DEFAULT,&dispid);
if(FAILED(hr))
{
ShowError(GetSystemErrorMessage(hr));
return false;
}
const int arraySize = paramArray.GetSize();
//Putting parameters
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = arraySize;
dispparams.rgvarg = new VARIANT[dispparams.cArgs];
dispparams.cNamedArgs = 0;
for( int i = 0; i < arraySize; i++)
{
CComBSTR bstr = paramArray.GetAt(arraySize - 1 - i); // back reading
bstr.CopyTo(&dispparams.rgvarg[i].bstrVal);
dispparams.rgvarg[i].vt = VT_BSTR;
}
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof excepInfo);
CComVariant vaResult;
UINT nArgErr = (UINT)-1; // initialize to invalid arg
//Call JavaScript function
hr = spScript->Invoke(dispid,IID_NULL,0,
DISPATCH_METHOD,&dispparams,
&vaResult,&excepInfo,&nArgErr);
delete [] dispparams.rgvarg;
if(FAILED(hr))
{
ShowError(GetSystemErrorMessage(hr));
return false;
}
return vaResult;
}
关于演示的说明
要从演示中调用 JavaScript 函数,你应该在左侧窗口的树中选择一个函数。之后,按下菜单栏上的“!”按钮。
历史
- 2011 年 7 月 7 日:更新了下载文件。