VC与JavaScript交互

这一章,我们来动手实践VC调用JS函数。

我们动手写一个HTML,其中包含这样一段JS代码:

[html] view
plain
copy

  1. <script type="text/javascript">
  2. function Add(value1, value2) {
  3. return value1 + value2;
  4. }
  5. </script>

然后我们用WebBrowser加载这个HTML后,在VC中这样来调用这个函数名为Add的JS函数:

[cpp] view
plain
copy

  1. //别忘了#include <MsHTML.h>
  2. //m_WebBrowser是一个WebBrowser的Activex控件对象。
  3. CComQIPtr<IHTMLDocument2> spDoc = m_WebBrowser.get_Document();
  4. CComDispatchDriver spScript;
  5. spDoc->get_Script(&spScript);
  6. CComVariant var1 = 10, var2 = 20, varRet;
  7. spScript.Invoke2(L"Add", &var1, &var2, &varRet);

spScript.Invoke2的作用是调用JS函数中名为Add的函数,传入两个参数,用varRet接收返回值。

可以看到,Invoke2调用成功后,varRet得到了返回值30。

但这样的话一次只能接受一个返回值。

如果要一次接受多个返回值的话,怎么办呢?

我们可以让JS返回一个JS中的Array数组或Object对象。

当JS函数return一个Array或一个Object对象时,VC这边的varRet将接受到一个代表该对象的IDispatch接口。我们仍然用CComDispatchDriver来管理这个IDispatch。用上一篇文章介绍的CComDispatchDriver的四个方法:

GetProperty

GetPropertyByName

PutProperty

PutPropertyByName

来从这个Array或Object对象中取出我们要的数据。

实践是检验真理的唯一标准,让我们再来写一个JS函数:

[html] view
plain
copy

  1. <script type="text/javascript">
  2. function Add(value1, value2) {
  3. var array = new Array();
  4. array[0] = value1;
  5. array[1] = value2;
  6. array[2] = value1 + value2;
  7. return array;
  8. }
  9. </script>

然后在VC中这样写:

[cpp] view
plain
copy

  1. CComQIPtr<IHTMLDocument2> spDoc = m_WebBrowser.get_Document();
  2. CComDispatchDriver spScript;
  3. spDoc->get_Script(&spScript);
  4. CComVariant var1 = 10, var2 = 20, varRet;
  5. spScript.Invoke2(L"Add", &var1, &var2, &varRet);
  6. CComDispatchDriver spArray = varRet.pdispVal;
  7. //获取数组中元素个数,这个length在JS中是Array对象的属性,相信大家很熟悉
  8. CComVariant varArrayLen;
  9. spArray.GetPropertyByName(L"length", &varArrayLen);
  10. //获取数组中第0,1,2个元素的值:
  11. CComVariant varValue[3];
  12. spArray.GetPropertyByName(L"0", &varValue[0]);
  13. spArray.GetPropertyByName(L"1", &varValue[1]);
  14. spArray.GetPropertyByName(L"2", &varValue[2]);

可以看到,10,20,30,这三个JS函数返回的值已经躺在我们的varValue[3]里了。

当然,如果不知道JS返回的Array对象里面有几个元素,我们可以在VC这边获取它的length属性,然后在一个循环中取出数组中的每个值。

如果我们的JS函数返回一个包含有多个属性值的Object对象,VC这边该如何接收呢?

让我们再来写一个JS函数:

[html] view
plain
copy

  1. <script type="text/javascript">
  2. function Add(value1, value2) {
  3. var data = new Object();
  4. data.result = value1 + value2;
  5. data.str = "Hello,我是小明!";
  6. return data;
  7. }
  8. </script>

然后在VC中我们这样接收:

[cpp] view
plain
copy

  1. CComQIPtr<IHTMLDocument2> spDoc = m_WebBrowser.get_Document();
  2. CComDispatchDriver spScript;
  3. spDoc->get_Script(&spScript);
  4. CComVariant var1 = 10, var2 = 20, varRet;
  5. spScript.Invoke2(L"Add", &var1, &var2, &varRet);
  6. CComDispatchDriver spData = varRet.pdispVal;
  7. CComVariant varValue1, varValue2;
  8. spData.GetPropertyByName(L"result", &varValue1);
  9. spData.GetPropertyByName(L"str", &varValue2);

我们从JS返回的Object对象里取出了它的两个属性,result和str,分别是一个整形数据和一个字符串。

这里JS代码是我们自己写的,在VC这边当然事先知道这个JS函数返回的对象有result和str这两个属性。

如果JS代码不是我们写的,或者它的属性是事先不能确定的,该怎么办呢?答案是使用IDispatchEx接口来枚举这个对象的相关信息(方法名、属性名)。

这个现在暂时不讲,在后续的文章中会讲。

当然,JS不只可以返回Object对象,返回什么对象都可以,当返回一个对象而非基本数据类型(整形、浮点、字符串)时,VC这边收到的返回值是一个IDispatch,然后我们需要调用GetPropertyByName方法从这个IDispatch代表的对象中取出它的属性来。

这样一来,VC调用JS函数,传递参数给JS和JS返回返回值给VC,大致就都会了。

对于CComVariant包装的VARIANT这种智能型变量,不了解的可以到网上看下相关资料。《深入解析ATL》之类的书上均有介绍。

值得注意的是ATL提供的这些CCom开头的智能包装类,并不依赖于ATL的动态库。因为我在VC项目中并没有选择链接ATL,程序调试运行时进程加载的模块中也有没有ATL100.dll之类的模块载入。大家可以放心使用而不用担心依赖上ATL。

参考:

http://blog.csdn.net/charlessimonyi/article/details/18450783

时间: 2024-08-08 09:37:36

VC与JavaScript交互的相关文章

VC与JavaScript交互(一) ———— 如何实现

为什么要让VC与JavaScript交互? 1.有时候我们需要让自己的软件打开一个网页,来获取页面上的一些数据.这时,可以用mshtml解析HTML提取出数据,也可以向HTML文档动态写入我们准备好的JS代码,用JS代码获取HTML上的数据,然后用VC调用该JS代码取得数据. 2.有时候我们需要让自己的软件打开一个网页并操控该网页,填写表单,提交等动作.这时,可以用mshtml操作HTML,给文本框赋值,模拟点击按钮.也可以向HTML文档动态写入我们准备好的JS代码,用JS代码实现填单,提交等动

VC与JavaScript交互(二)

最近关于vc++里面通过IDispatch的Invoke来实现和js的交互做点了tp,并且对以前不了解的"直接读取js变量值"和"传递多个参数"的部分重新实现了下. 1,调用js的函数,并传递多个参数 CComQIPtr<IHTMLDocument2> pDoc = m_browser.get_Document(); if (pDoc) { CComQIPtr<IDispatch> spDisp; HRESULT hr = pDoc->

VC与JavaScript交互(二) ———— 调用JS函数

这一章,我们来动手实践VC调用JS函数. 我们动手写一个HTML,其中包含这样一段JS代码: [html] view plaincopy <script type="text/javascript"> function Add(value1, value2) { return value1 + value2; } </script> 然后我们用WebBrowser加载这个HTML后,在VC中这样来调用这个函数名为Add的JS函数: [cpp] view plai

VC与JavaScript交互(三) ———— CWebPage类调用javascript函数(给js函数传参,并取得返回值)

①需要一个别人写好的类CWebPage,将其对于的两个文件WebPage.h和WebPage.cpp添加到工程中. ②添加WebBrowser控件,在视图/对话框类的头文件中#include "webbrowser2.h",增加成员变量m_webBrowser,调用Navigate()函数加载一个html页面. ③在对话框或者视图的实现文件中,加入#include "WebPage.h",在按钮的响应函数中就可以调用javascript函数了,具体代码如下: CWe

WPF加载HTML、WPF与JavaScript交互

目录 一.WebBrowser加载远程网页 二.WebBrowser加载本地网页,注:不可以加载本地样式CSS和脚本JS文件 三.WebBrowser隐藏网页的JavaScript错误 四.网页屏蔽鼠标右键.Ctrl+N.Shift+F10.F11.F5刷新.退格键 五.WPF程序与网页JavaScript交互 六.创建服务器,提供数据接口.Script.CSS文件 一.WebBrowser加载远程网页 wbrExam.Source = new Uri("http://cnblogs.com/s

Objective-C与JavaScript交互的那些事

最近公司的运营瞎搞了个活动,其活动要服务端提供数据支持,web前端在微信公众账号内作为主要的运营阵地,而iOS.Android要提供相应的入口及页面进行配合.一个活动,动用了各个端的程序猿.而在这里面技术方面主要就是涉及到web端和服务端的交互,web前端和iOS.Android的交互.本人作为一个iOS开发者,今天就聊聊web.iOS.Android三端的交互,其实在说明白一点就是方法的互相调用而已.这里主要讲解iOS.Android会稍微提一下,仅作参考. 此篇文章的逻辑图 图0-0 此篇文

IOS中UIWebView和JavaScript交互(转自http://blog.2jun.net/2012/11/02/webviewandjs/)

IOS中UIWebView和JavaScript交互 当程序中使用到UIWebView控件的时候,难免会遇到需要与页面进行交互的情况.这种情况在android平台下比较容易处理,android平台下WebView控件的addJavascriptInterface()方法可以很轻松的完成交互,而IOS上就稍复杂一些. 页面与客户端的交互是通过JS来完成的,通常情况下与JS的交互可以分为两种:客户端传递给JS一些数据和JS向客户端请求一些本地操作.下面分别对这两种情况进行处理. JS向客户端请求本地

Android WebView JavaScript交互

今天介绍一下,Android中Webview与JavaScript的交互,首先是在布局文件里添加webview控件: [html] view plaincopy <WebView android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> 然后是在manifest里添加权限: [html] vie

Xcode6 UIWebView与JavaScript交互(issue fix)

这篇文章中,有介绍UIWebView与JavaScript交互,在UIWebView截获JavaScript请求处理,从app的角度,这是JavaScript的Hook请求. 在Xcode6之前的App版本,JavaScript可以这样将Hook请求发送出来: HTML: <li><a href="testapp://function=test&callbackJS=testCallback">test link</a></li>