VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 2637|回复: 12

[分享] VC与JavaScript交互(二):调用JS函数

[复制链接]
51_avatar_middle
online_admins 发表于 2014-9-10 13:44:33 | 显示全部楼层 |阅读模式
书接上文:
VC与JavaScript交互(一): 如何实现
https://www.cctry.com/thread-243573-1-1.html


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

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

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


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

  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);
复制代码


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

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函数:

  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中这样写:

  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.        
  7. CComDispatchDriver spArray = varRet.pdispVal;
  8. //获取数组中元素个数,这个length在JS中是Array对象的属性,相信大家很熟悉
  9. CComVariant varArrayLen;
  10. spArray.GetPropertyByName(L"length", &varArrayLen);
  11. //获取数组中第0,1,2个元素的值:
  12. CComVariant varValue[3];
  13. spArray.GetPropertyByName(L"0", &varValue[0]);
  14. spArray.GetPropertyByName(L"1", &varValue[1]);
  15. spArray.GetPropertyByName(L"2", &varValue[2]);
复制代码


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

可以看到,10,20,30,这三个JS函数返回的值已经躺在我们的varValue[3]里了。
当然,如果不知道JS返回的Array对象里面有几个元素,我们可以在VC这边获取它的length属性,然后在一个循环中取出数组中的每个值。

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

  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中我们这样接收:

  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.        
  7.         CComDispatchDriver spData = varRet.pdispVal;
  8.         CComVariant varValue1, varValue2;
  9.         spData.GetPropertyByName(L"result", &varValue1);
  10.         spData.GetPropertyByName(L"str", &varValue2);
复制代码


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

我们从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。

VC调用JS函数没问题了。那么JS函数如何调用VC呢?我们将在下一篇文章中慢慢道来。




上一篇:VC与JavaScript交互(一): 如何实现
下一篇:VC开发 Http-Post 程序的三种常用方法[Web机器人]
09_avatar_middle
online_vip 发表于 2014-9-10 20:26:37 | 显示全部楼层
学习啦,这段也与JavaScript打交道

点评

很好!  发表于 2014-10-15 10:00
14_avatar_middle
在线会员 发表于 2014-10-15 09:52:18 | 显示全部楼层
不错,支持!
14_avatar_middle
在线会员 发表于 2014-10-15 09:53:27 | 显示全部楼层
感谢楼主分享!
14_avatar_middle
在线会员 发表于 2014-10-15 09:53:59 | 显示全部楼层
顶起来!
14_avatar_middle
在线会员 发表于 2014-10-15 09:54:44 | 显示全部楼层
感谢楼主这种分享的精神!
14_avatar_middle
在线会员 发表于 2014-10-15 09:55:22 | 显示全部楼层
对大家有用的就是好贴!
14_avatar_middle
在线会员 发表于 2014-10-15 09:55:50 | 显示全部楼层
好贴是必须要顶的!
14_avatar_middle
在线会员 发表于 2014-10-15 09:57:17 | 显示全部楼层
楼主很用心,写的也很详细!
14_avatar_middle
在线会员 发表于 2014-10-15 09:58:35 | 显示全部楼层
也感谢这个论坛,给大家一个这么好的平台!
10_avatar_middle
在线会员 发表于 2014-10-17 09:21:47 | 显示全部楼层
不错的技术分享
62_avatar_middle
online_vip 发表于 2017-3-19 17:04:19 | 显示全部楼层
很好的技术
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-9-16 13:12

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表