65.9K
CodeProject 正在变化。 阅读更多。
Home

从 C++ 调用 JavaScript

2002 年 5 月 29 日

CPOL

2分钟阅读

viewsIcon

581557

downloadIcon

20749

一个用于从 C++ 代码轻松实现 JavaScript 调用的类。

Sample Image

引言

有时在使用 C++ 应用程序中的 IE 浏览器控件时,你需要访问 HTML 元素。我们可以使用标准的 COM 对象,如 IWebBrowser2IHTMLDocument2 等来实现。通过这种方法,我们可以轻松实现诸如点击按钮、点击锚点、获取输入字符串、获取 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 日:更新了下载文件。
© . All rights reserved.