zoukankan      html  css  js  c++  java
  • VC与JavaScript交互(一) ———— 怎样实现

    为什么要让VCJavaScript交互?

    1.有时候我们须要让自己的软件打开一个网页。来获取页面上的一些数据。

    这时,能够用mshtml解析HTML提取出数据。也能够向HTML文档动态写入我们准备好的JS代码,用JS代码获取HTML上的数据,然后用VC调用该JS代码取得数据。

    2.有时候我们须要让自己的软件打开一个网页并操控该网页,填写表单,提交等动作。这时。能够用mshtml操作HTML,给文本框赋值,模拟点击button。

    也能够向HTML文档动态写入我们准备好的JS代码,用JS代码实现填单,提交等动作,然后用VC调用一下JS代码就可以。

    3.有时候我们须要用HTML网页做界面。用JS管理HTML页面,用VC调用JS传递进数据。JS把这些数据通过HTML显示在界面上。CHtmlDialog正是这样的产物。

    4.有时候我们须要基于HTTP协议与WEBserver直接交互。比方基于HTTP协议来登录QQ空间。可是对浏览器抓包发现QQ号是明文传输,但QQpassword是密文。它是怎样加密的呢?这些加密算法肯定都在页面上的JS里。由于这个加密过程是在客户浏览器上实现的。我们能够找到加密相关的JS代码,细致阅读分析。改写为C++代码实现,但比較复杂。一个简单的办法就是直接把这些用于加密的JS代码复制出来,用VC调用JS代码,让它的JS代码完毕加密过程。然后我们把密文拿过来,用HTTP协议POST发送到WEBserver,即完毕了登陆动作。

    5.等等,还有非常多用途。


    那么。在Windows平台上用VC开发的程序。怎样与JavaScript交互?

    通常,我们都是用WebBrowser载入包括JS代码的HTML。然后通过WebBrowser对象获取IHTMLDocument接口(对于ActiveXWebBrowser来说是get_Document方法,对于CHtmlView对象来说是GetHtmlDocument方法)。当中IHTMLDocument2接口有一个get_Script方法,能够获取用于控制JS代码的IDispatch接口。

    VC调用JS函数,都是通过这个IDispatch接口的Invoke方法来完毕。使用IDispatch接口的GetIDsOfNames方法依据JS函数名获取调度标识符DISPID。使用Invoke来调用JS函数。Invoke最后两个參数用于返回错误信息。可为NULL。这个IDispatch接口调用起来非常麻烦,下文将会介绍怎样简便的调用。

    网上有个外国人写了个CWebPage类实现VCJS交互,用的正是这样的方法。

    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并什么也不写。

    由于默认的PostNcDestroydelete  this;而出错。

    假设是在堆上创建CHtmlView对象则要注意防止二次delete。

    还有一种方法是使用WebBrowserActiveX控件。这样的方法能够在MFC项目中使用,也能够在非MFC项目中使用。


    关于IDispatch

    我们知道IDispatchCOM双接口中的调度接口。一般用于供脚本语言调用COM组件。对于编译型的C++语言。让它调用这样的接口,是非常麻烦的。

    毕竟用IDispatch接口调用COM对象的各种方法、设置与获取COM对象的属性、让COM对象回调我们,都是用IDispatchInvoke方法来实现。一个Invoke就要实现那么多功能,用起来当然非常麻烦。

    只是好在ATL智能指针类中的CComDispatchDriver(CComQIPtr<IDispatch>)封装了IDispatch接口。使用我们用起来大大的方便!CComDispatchDriverGetIDsOfNamesInvoke进一步进行了封装。仅仅需更少的參数即方便可调用。

    获取和设置COM对象属性能够用CComDispatchDriver的这些方法:

    GetProperty

    GetPropertyByName

    PutProperty

    PutPropertyByName

    事实上使用IDispatch调度接口来设置、获取COM属性。调用COM方法。都是使用GetIDsOfNamesInvoke

    实际上这四个方法都是对GetIDsOfNamesInvoke的封装。

    简化调用的复杂性。

    调用COM对象的方法能够用这些方法:

    Invoke0    //调用0个參数的方法

    Invoke1    //调用1个參数的方法

    Invoke2    //调用2个參数的方法

    InvokeN    //调用多个參数的方法

    这些函数都有两个版本号,一个是接受调度标示符DISPID,须要自己先调用GetIDsOfNames来获取。

    一个是接受OLE字符串的版本号,这个版本号在内部会调用GetIDsOfNames来获取DISPID。这些函数用起来非常方便,不须要我们自己填充DISPPARAMS结构,可是它对原始Invoke的调用时,最后两个參数都是NULL,即不须要获取错误信息。假设须要获取错误信息,我们须要自行调用原始Invoke方法。

    注意。这些方法是ALTCComDispatchDriver封装的方法,调用时应使用"."而不是"->"。由于"->"获得的是CComDispatchDriver内部的Dispatch指针。

    还有一个要注意的问题是,一定要等Navigate全然载入一个html文档后(触发OnDocumentComplete)。才干获取IHTMLDocument2Script

    否则会出现空指针或找不到JS函数。所以不能在调用Navigate打开HTML后就紧接着获取IHTMLDocument2Script,要等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函数看看。


  • 相关阅读:
    OneThink友情链接插件使用!
    OneThink生成分类树方法(list_to_tree)使用!
    OneThink视图模型进行组合查询!文档组合文档详情
    Atitit.数据操作dsl 的设计 ---linq 方案
    Atitit.数据操作dsl 的设计 ---linq 方案
    Atitit.Atiposter 发帖机 信息发布器 v7 q516
    Atitit.Atiposter 发帖机 信息发布器 v7 q516
    Atitit.http连接合并组件   ConnReducerV3 新特性
    Atitit.http连接合并组件   ConnReducerV3 新特性
    Atitit.减少http请求数方案
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7085276.html
Copyright © 2011-2022 走看看