浏览器插件之ActiveX开发(四)_weixin_30951231的博客-程序员宅基地

技术标签: ViewUI  ui  javascript  c/c++  

    简单总结一下前几篇文章的内容,《浏览器插件之ActiveX开发(一)》简单介绍了一下如何在Vs.net 2008下用C++开发基于MFC的ActiveX插件,《浏览器插件之ActiveX开发(二)》介绍了开发插件时可能遇到的问题,《浏览器插件之ActiveX开发(三)》介绍了如何注册插件以及如何打包成cab文件。但是,到目前为止还没有专门提及如何在Web页面中调用插件,本文主要针对这个问题进行展开。

 

一、用<Object>标签调用ActiveX

    1、Object标签基本用法

    在Html页面中调用ActiveX插件最简单常用的方法是:

<object id="CardAccessor" 
    classid="clsid:03AD53E8-D7E7-485D-A39A-D07B37DEFBC9"     
    width="0" 
    height="0">
</object>

    id属性就不用解释了,和html中其他元素的id一样,是DOM树中各元素的唯一标识。width和height表示该ActiveX在Web页面中占位的大小,对于仅提供接口无UI界面的ActiveX来说将其设置为0即可,因为不需要在页面上显示任何内容(对于需要显示界面的ActiveX,需要在项目里创建Dialog及写相应逻辑,可以参考“A Complete ActiveX Web Control Tutorial”实例 )。

    classid属性在这里是一个非常关键的属性,IE正是通过他才能正确找到要调用的ActiveX的。每个ActiveX均有一个唯一的id来表示,这就是classid,在我们创建MFC ActiveX Control项目时Vs.net 2008就帮我们生成了这个id, 可以在程序的.idl文件最下方找到这个ID值:

             image

     一般不建议手动修改程序中的这个uuid值,因为在xxxxCtrl.cpp文件中也用到了这个id值,只是表现形式不一样罢了:

            image

      控件注册成功后,这个classid及控件文件位置等信息均写入注册表了,如下所示:

            image

      当然,如果ActiveX还定义了其他属性,也可以在<object>中以属性的形式给他们赋值。

 

      如果用户的计算机已经注册了该插件(例如通过Setup.exe方式),那么Html引用上段代码后就可以通过js调用插件的接口和属性了(再次提示一下,ActiveX只能在IE浏览器运行,也就是<object…>这段代码在firefox等其他浏览器是不能正常工作的)。   

<fieldset>
         <legend>Read Card No Testing</legend>
         卡号:<input type="text" id="txtCardNo_Read" maxlength="32" class="txt disable" readonly />
         <input type="button" id="btnRead" value=" Read CardNo " class="btn" onclick="javascript:readCardNo();" />
    </fieldset>
    
    <fieldset>
         <legend>Write Card No Testing</legend>
         卡号:<input type="text" id="txtCardNo_Write" maxlength="32" class="txt" />
         <input type="button" id="btnWrite" value=" Write CardNo " class="btn" onclick="javascript:writeCardNo();" />
    </fieldset>

<script type="text/javascript">
    var txtCardNo_Read = document.getElementById("txtCardNo_Read");
    var txtCardNo_Write = document.getElementById("txtCardNo_Write");
    var objCard = document.getElementById("CardAccessor");
   
    function readCardNo() {
        txtCardNo_Read.value = "";
        
        try{
            var ret = objCard.ReadCardNo();
            
            if (ret == 0) {
                txtCardNo_Read.value = objCard.CardNo;
                alert("读卡成功!");
            }
            else {
                alert("读卡失败!错误码为:" + ret);
            }
        }
        catch (e) {
            alert(e.message)
        }
    }

    function writeCardNo() {
        var cardNo = txtCardNo_Write.value;

        try {
            objCard.CardNo = cardNo;
            var ret = objCard.WriteCardNo();

            if (ret == 0) {                
                alert("写卡成功!");
            }
            else {
                alert("写卡失败!错误码为:" + ret);
            }
        }
        catch (e) {
            alert(e.message)
        }
    }
      
</script>

 

    2、使用Object标签时如何判断ActiveX是否已注册

<script type="text/javascript">
    var objCard = document.getElementById("CardAccessor");

    if (objCard.object==null) {
        alert("CardAccessor插件未安装!");
    }
    else{
        alert("已检测到CardAccessor插件!");
    }
</script>

        另外也可以通过访问ActiveX中的某个已知已定义的属性来判断插件是否已安装,如果返回的属性值为undefined,则表示没有检测到插件。例如:

<script type="text/javascript">
    var objCard = document.getElementById("CardAccessor");

    if (objCard.CardNo==undefinedl) {
        alert("CardAccessor插件未安装!");
    }
    else{
        alert("已检测到CardAccessor插件!");
    }
</script>

 

   3、如何让IE自动下载安装插件并智能升级

       如果检测到插件没有安装,怎样让IE自动从指定位置下载插件并自动安装呢?很简单,在object标签中使用codebase属性即可:

<object id="CardAccessor" 
    classid="clsid:03AD53E8-D7E7-485D-A39A-D07B37DEFBC9" 
    ="CardAccessor.cab#version=1,0,0,1"
    width="0" 
    height="0">
</object>

     codebase的值格式为“xxxxx.cab#version=1,0,0,1”。'#'前面部分为cab文件的位置,可以是在服务器上的绝对位置,也可以是相对位置。'#‘后面部分表示当前引用的cab包的版本号。当IE检测到系统没有注册指定插件,便从codebase指定的位置下载该cab到本地,并按照其中.inf文件的描述将各文件复制到指定位置并注册指定的控件。(注:在实际应用中涉及签名问题,后文再述

     即使本地已经注册了该插件,IE还将拿已注册的控件版本号与codebase中指定的版本号相比较,如果codebase中指定的版本号大于已注册插件的版本号,IE仍然会从codebase指定位置下载cab包并重新注册该插件。

     正如前面的文章所提,为方便管理,一般将cab包中需注册的ocx文件的版本号视同cab版本号。

     当插件或插件依赖的文件需要升级时,只需更新相应的文件,并对.inf中的相应文件版本升级(为方便管理,无论是否更新了ocx文件,该ocx文件的版本号也跟着升级,因为其版本号代表了整个cab),然后重新打包成cab发布到服务器上,并更新html中object标签中codebase属性值的version部分版本号。当用户下次访问该页面时,IE将自动下载升级后的cab并重新注册插件。实际上,经过我的测试,及时服务器上的cab包不做任何变化,只要增加codebase中version的值,对应插件均会重新下载和注册。

 

二、通过javascript的new ActiveXObject来调用ActiveX

      如果不使用object标签,也可以直接通过js的ActiveXObject来创建指定ActiveX的实例从而达到调用插件接口的目的(IE下xmlhttpRequest的调用就是这个原理)。例如:

var objCard = new ActiveXObject("Uprain.CardAccessorCtrl.1");

      如果插件已经注册,接下来就可以通过objCard来调用插件接口和访问属性了。

      ActiveXObject函数的参数为对应插件的ProgId而非CLASSID。在项目中xxxxCtrl.cpp文件中同样可以找到或修改对应插件的ProgId值,如下图:

       image

     即IMPLEMENT_OLECREATE_EX的第二参数就表示当前插件的ProgId,该值可以根据实际需要自行修改。实际上,在注册表中通过ProgId是可以找到对应的ClassId的,两者是有关联的:

        image

 

      那么如何判断ActiveX是否已经安装呢?实际上如果ActiveX未安装,通过new ActiveXObject的方式来创建插件对象是会抛出“Automation 服务器不能创建对象”异常的。所以用如下方式即可:

try {
         objCard = new ActiveXObject("Uprain.CardAccessorCtrl.1");                
    }
catch (e) {
         alert("调用ActiveX失败!");
    }

 

    不过,我在实际测试过程中遇到两种情况:

     1) 出现“Automation 服务器不能创建对象”异常的并不一定就表示插件没安装,也有可能是因插件未实现初始化或脚本安全接口,从而被IE拦截,需要调整IE“工具-选项-安全-自定义级别”中“ActiveX控件和插件”部分的设置;

     2) 有时候,同样已注册的插件,通过object标签引用的方式能正常调用接口,但通过new ActiveXObject的方式则调用插件接口失败。

转载于:https://www.cnblogs.com/qguohog/archive/2013/01/25/2876828.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30951231/article/details/96586619

智能推荐

64位Win8系统下安装Oracle12c_diaobiao8107的博客-程序员宅基地

过3个小时的折腾,终于在64位win8系统下成功安装了Oracle 12c。这篇文章主要把安装过程中遇到的一些问题总结一下,以便帮助后来人参考。首先我把我的机器的主要配制情况列举出来:1、 系统:win8,64位2、 内存:8G一、下载Oracle 12c直接到Oracle官网进行下载就可以了,地址为:http://www.oracle.com/technetwork...

2018 存储技术热点与趋势总结_ganggexiongqi的博客-程序员宅基地

过去半年阅读了 30 多篇论文,坚持每 1~2 周写一篇 Newsletter,大部分都和存储相关。今天在这里进行一个总结,供大家作为了解存储技术热点和趋势的参考。本文包含了全新的技术领域,如 Open-Channel SSD,Machine Learning for Systems;也包含老话题的新进展,如 NVM,LSM-Tree,Crash Consistency;以及工业界的进展。Open...

模糊控制 MATLAB 仿真_熠晨的博客-程序员宅基地_模糊函数matlab

参考《智能控制》第三章以模糊洗衣机的设计为例,其控制是一个开环的决策过程,模糊控制按以下步骤进行。(1)模糊控制器的结构    选用单变量二维模糊控制器。控制器的输入为衣物的污泥和油脂,输出为洗涤时间。(2)定义输入输出模糊集   X:将污泥分为三个模糊集:SD(污泥少),MD(污泥中),LD(污泥多),取值范围为[0,100]。   Y:将油脂分为三个模糊集:NG(无油脂...

Linux实现ssh基于key验证的免密登录_白-胖-子的博客-程序员宅基地

ssh基于key验证机制连接自己必须先在本地生成自己的公钥和私钥要连接谁就要把自己的公钥放到谁的服务器上实现免密的逻辑服务器端拿客户端公钥加密随机字符传给客户端客户端解密后再拿服务器公钥加密传给服务器端实现免密的意义公钥放在目录里一行一个,多个公钥比用户名和密码更安全每次服务器互相连接的时候不再需要输入密码了实现ssh免密登录客户端生成公钥私钥对ssh-keygenssh-keygenGenerating public/private rsa key pair

芯钰科运动控制应用机器视觉- 机器视觉(1)-安装配置_evenou的博客-程序员宅基地_vision development module 8.6.4

基于LABVIEW的机器视觉开发是采用LABVIEW Vision8.6版本的,感觉8.6的比较稳定些,2010的上次下了一个USB的控件一直没出来,所以没有继续配置了。配置步骤如下:首先去官方网站下载:1.Vision Development Module 8.6.4http://joule.ni.com/nidu/cds/view/p/id/1220/lang/en2.

使用radiobutton实现底部导航栏_im哆来咪的博客-程序员宅基地

很多app中,都有底部导航栏。点击不同的菜单,就会显示不同的界面。 实现底部导航栏的方式有很多,最容易想到的就是是imageview+textview。当然还有一些别的方法,例如完全可以通过radiobutton来实现这个功能。 先来看布局:<RadioGroup android:layout_width="match_parent" androi

随便推点

C++ (opencv)读取文件夹下所有的图片(某一种类型,如JPG)(一次性读取)_SoftGit的博客-程序员宅基地_c++读取文件夹下所有图片

`/testpath下面有两个文件夹,一个RGBFace,一个DepthFace,所有的图片都是彩色和PNG的 //读取文件夹下的图片文件名称 vector files; //string filepath_RGB = testpath + “/RGBFace/*.jpg”; string filepath_RGB = “E:/*.jp...

Python编译报错的自我记录_f3611018的博客-程序员宅基地

1.yaml.parser.ParserError: expected '&lt;document start&gt;', but found '&lt;scalar&gt;'这个后面会跟报错的是哪个文件,第几行。 仔细检查一下,是不是有中文的标点符号,当时我是应为中文的:,导致的这种的报错。2.yaml.parser.ParserError: expected '&lt;d...

@Scheduled(cron="") spring定时任务时间设置_延卿的博客-程序员宅基地

一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。按顺序依次为秒(0~59)分钟(0~59)小时(0~23)天(月)(0~31,但是你需要考虑你月的天数)月(0~11)天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)7.年份(1970-2099)其中每个元素可以是一个值(如6),一个连续区间(9-

Android音量设置流程干货版_我把葡萄酿成酒的博客-程序员宅基地

1.     音量级数定义在AudioService.java中定义了最大音量MAX_STREAM_VOLUME,手机的设置property可以覆盖它。2.     音量初始化initStreamVolume传入AudioPolicyManagerBase里的StreamDescriptor mStreams[AudioSystem::NUM_STREAM_TYPES];3.

Hexo博客如何写文章?_迷途小书童的Note的博客-程序员宅基地_hexo如何写文章

原文链接https://xugaoxiang.com/2019/09/19/Hexo博客写文章/

在Linux下使用perl通过unixODBC连接SQLServer2000_god9me的博客-程序员宅基地

作者:tonyvicky来自:LinuxSir.Org摘要:MS从来没有提供过SQLServer for Linux,所以大家也不要去尝试在Linux系统安装SQLServer,但是可以通过ODBC连接Windows系统的SQLServer数据库;目录一、关于测试环境及Linux连接SQL Server 的说明;二、下载相关软件 unixODBC、freetds和DBD-ODBC三、安

推荐文章

热门文章

相关标签