VC与JavaScript交互(一) --- 如何实现
为什么要让VC与JavaScript交互?
1.有时候我们需要让自己的软件打开一个网页,来获取页面上的一些数据。这时,可以用mshtml解析HTML提取出数据,也可以向HTML文档动态写入我们准备好的JS代码,用JS代码获取HTML上的数据,然后用VC调用该JS代码取得数据。
2.有时候我们需要让自己的软件打开一个网页并操控该网页,填写表单,提交等动作。这时,可以用mshtml操作HTML,给文本框赋值,模拟点击按钮。也可以向HTML文档动态写入我们准备好的JS代码,用JS代码实现填单,提交等动作,然后用VC调用一下JS代码即可。
3.有时候我们需要用HTML网页做界面,用JS管理HTML页面,用VC调用JS传递进数据,JS把这些数据通过HTML显示在界面上。CHtmlDialog正是这种产物。
4.有时候我们需要基于HTTP协议与WEB服务器直接交互。比如基于HTTP协议来登录QQ空间。但是对浏览器抓包发现QQ号是明文传输,但QQ密码是密文,它是如何加密的呢?这些加密算法肯定都在页面上的JS里,因为这个加密过程是在客户浏览器上实现的。我们可以找到加密相关的JS代码,仔细阅读分析,改写为C++代码实现,但比较复杂。一个简单的办法就是直接把这些用于加密的JS代码复制出来,用VC调用JS代码,让它的JS代码完成加密过程,然后我们把密文拿过来,用HTTP协议POST发送到WEB服务器,即完成了登陆动作。
5.等等,还有很多用途。
那么,在Windows平台上用VC开发的程序,如何与JavaScript交互?
通常,我们都是用WebBrowser加载包含JS代码的HTML,然后通过WebBrowser对象获取IHTMLDocument接口(对于ActiveX的WebBrowser来说是get_Document方法,对于CHtmlView对象来说是GetHtmlDocument方法)。其中IHTMLDocument2接口有一个get_Script方法,可以获取用于控制JS代码的IDispatch接口。VC调用JS函数,都是通过这个IDispatch接口的Invoke方法来完成。使用IDispatch接口的GetIDsOfNames方法根据JS函数名获取调度标识符DISPID,使用Invoke来调用JS函数。Invoke最后两个参数用于返回错误信息,可为NULL。这个IDispatch接口调用起来很麻烦,下文将会介绍如何简便的调用。网上有个外国人写了个CWebPage类实现VC与JS交互,用的正是这种方法。
http://www.codeproject.com/Articles/2352/JavaScript-call-from-C
关于WebBrowser:
在VC中使用WebBrowser,一般有两种方法。MFC中有个CHtmlView封装了WebBrowser,用起来很方便。虽然CHtmlView派生于CView,是个视图类,但它也派生于CWnd,将其用于对话框上,完全没有问题,只是在某些地方需要小修改一下。其中需要注意的两个问题就是:
1. CHtmlView的构造函数是protected的,不允许直接构造一个CHtmlView对象。必须从CHtmlView派生后再构造。
2.如果是在栈上创建CHtmlView对象,必须重载PostNcDestroy并什么也不写。因为默认的PostNcDestroy会delete this;而出错。如果是在堆上创建CHtmlView对象则要注意防止二次delete。
另一种方法是使用WebBrowser的ActiveX控件,这种方法可以在MFC项目中使用,也可以在非MFC项目中使用。
关于IDispatch:
我们知道IDispatch是COM双接口中的调度接口。一般用于供脚本语言调用COM组件。对于编译型的C++语言,让它调用这种接口,是很麻烦的。毕竟用IDispatch接口调用COM对象的各种方法、设置与获取COM对象的属性、让COM对象回调我们,都是用IDispatch的Invoke方法来实现。一个Invoke就要实现那么多功能,用起来当然很麻烦。不过好在ATL智能指针类中的CComDispatchDriver(即CComQIPtr<IDispatch>)封装了IDispatch接口,使用我们用起来大大的方便!CComDispatchDriver对GetIDsOfNames和Invoke进一步进行了封装,只需更少的参数即方便可调用。
获取和设置COM对象属性可以用CComDispatchDriver的这些方法:
GetProperty
GetPropertyByName
PutProperty
PutPropertyByName
其实使用IDispatch调度接口来设置、获取COM属性,调用COM方法,都是使用GetIDsOfNames和Invoke。实际上这四个方法都是对GetIDsOfNames和Invoke的封装。简化调用的复杂性。
调用COM对象的方法可以用这些方法:
Invoke0 //调用0个参数的方法
Invoke1 //调用1个参数的方法
Invoke2 //调用2个参数的方法
InvokeN //调用多个参数的方法
这些函数都有两个版本,一个是接受调度标示符DISPID,需要自己先调用GetIDsOfNames来获取。一个是接受OLE字符串的版本,这个版本在内部会调用GetIDsOfNames来获取DISPID。这些函数用起来很方便,不需要我们自己填充DISPPARAMS结构,但是它对原始Invoke的调用时,最后两个参数都是NULL,即不需要获取错误信息。如果需要获取错误信息,我们需要自行调用原始Invoke方法。
注意,这些方法是ALT的CComDispatchDriver封装的方法,调用时应使用"."而不是"->"。因为"->"获得的是CComDispatchDriver内部的Dispatch指针。
另一个要注意的问题是,一定要等Navigate完全加载一个html文档后(触发OnDocumentComplete)。才能获取IHTMLDocument2和Script。否则会出现空指针或找不到JS函数。所以不能在调用Navigate打开HTML后就紧接着获取IHTMLDocument2和Script,要等HTML文档加载完。
上面说了这么多COM对象,和VC调用JS有什么关系?别忘了我们用IHTMLDocument2接口的get_Script方法获取到了代表HTML文档中JS代码的IDispatch接口,我们用IDispatch接口,把HTML文档中的这堆JS代码当作一个COM对象,来操控它。上面说的Invoke0,Invoke1,Invoke2,InvokeN,正是分别被我们用来调用0个参数的JS函数,1个参数的JS函数,2个参数的JS函数,N个参数的JS函数。
说了那么多,下一篇文章,让我们来实际动手,用VC调用一下JS函数看看。
VC与JavaScript交互(一) --- 如何实现的更多相关文章
- VC与JavaScript交互(一) ———— 怎样实现
为什么要让VC与JavaScript交互? 1.有时候我们须要让自己的软件打开一个网页.来获取页面上的一些数据. 这时,能够用mshtml解析HTML提取出数据.也能够向HTML文档动态写入我们准备好 ...
- VC与JavaScript交互(二) --- 调用JS函数
这一章,我们来动手实践VC调用JS函数. 我们动手写一个HTML,其中包含这样一段JS代码: //[html] <script type="text/javascript"& ...
- VC与JavaScript交互(四) --- WebBrowser或CHtmlView中轻松屏蔽脚本错误(JavaScript)
1.什么是javascript脚本错误 1.1 概述 JavaScript脚本错误包含“运行时错误”和“语法错误”. 1.2 JavaScript“语法错误” JavaScript语法错误 ...
- VC与JavaScript交互(三) --- CWebPage类调用javascript函数(给js函数传参,并取得返回值)
①需要一个别人写好的类CWebPage,将其对于的两个文件WebPage.h和WebPage.cpp添加到工程中. ②添加WebBrowser控件,在视图/对话框类的头文件中#include &quo ...
- Android混合开发之WebView与Javascript交互
前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App.Web App.Hybrid App三种方式,个人觉得目前以Hybri ...
- 移动端基于HTML模板和JSON数据的JavaScript交互
写本文之前,我正在做一个基于Tab页的订单中心: 每点击一个TAB标签,会请求对应状态的订单列表.之前的项目,我会在js里使用 + 连接符连接多个html内容: var html = ''; htm ...
- 重新想象 Windows 8.1 Store Apps (80) - 控件增强: WebView 之基本应用, POST 数据, 与 JavaScript 交互
[源码下载] 重新想象 Windows 8.1 Store Apps (80) - 控件增强: WebView 之基本应用, POST 数据, 与 JavaScript 交互 作者:webabcd 介 ...
- MongoDB源码分析——mongo与JavaScript交互
mongo与JavaScript交互 源码版本为MongoDB 2.6分支 之前已经说过mongo是MongoDB提供的一个执行JavaScript脚本的客户端工具,执行js其实就是一个js和 ...
- Android WebView JavaScript交互
今天介绍一下,Android中Webview与JavaScript的交互,首先是在布局文件里添加webview控件: <WebView android:id="@+id/webview ...
随机推荐
- (PowerShell) Managing Windows Registry
http://powershell.com/cs/blogs/ebookv2/archive/2012/03/23/chapter-16-managing-windows-registry.aspx
- memwatch
一.简介 memwatch可以跟踪程序中的内存泄漏和错误,能检测双重释放(double-free).错误释放(erroneous free).没有释放的内存(unfreed memory).溢出(Ov ...
- Servlet概述及其生命周期
Servlet和传统CGI程序相比的优点: 1. 只需要启动一个操作系统进程以及加载一个JVM,大大降低了系统的开销 2. 如果多个请求需要做同样处理的时候,这时只需要加载一个类,这也大大降低了开 ...
- HDU5221 Occupation 树链剖分
题意: 给出一棵树,root=1,树有点权,有一个人叫做M 有3种操作: 1 u v 把u到v路径上的所有点的点权都给M 2 u 若u的点权在M手上,拿走 3 u 把u为根的子树的所有点权都给M 每一 ...
- CF 161D Distance in Tree 树形DP
一棵树,边长都是1,问这棵树有多少点对的距离刚好为k 令tree(i)表示以i为根的子树 dp[i][j][1]:在tree(i)中,经过节点i,长度为j,其中一个端点为i的路径的个数dp[i][j] ...
- linux查看和开放某端口
查看某端口是否已打开: netstat -nulp //UDP端口netstat -ntlp //TCP端口 或者:lsof -i:port-num 开放某端口: 在/etc/sysconfig/ip ...
- SVN---脱离SVN控制
创建一个记事本文件,然后吧这句话复制进去for /r . %%a in (.) do @if exist "%%a\.svn" rd /s /q "%%a\.svn&qu ...
- NSPredicate,谓词
原文地址:http://blog.csdn.net/holydancer/article/details/7380799 在语言上,谓语,谓词是用来判断的,比如“我是程序猿”中的是,就是表判断的谓语, ...
- iOS学习笔记总结整理
来源:http://mobile.51cto.com/iphone-386851_all.htm 学习IOS开发这对于一个初学者来说,是一件非常挠头的事情.其实学习IOS开发无外乎平时的积累与总结.下 ...
- solr学习之添加文档
一.开篇语 其实Solr就是一个你可以通过他来查询文档的东西,他整个都是基于Document的,那么这些Document从何而来列? 当然是我们给他,而这些来源就包括了:数据库文件,XML,Json ...