• 浏览器插件之ActiveX开发(二)


         按照上文《浏览器插件之ActiveX开发(一)》的步骤,能开发一个基于MFC的简单的ActiveX控件。不过在实际操作中还是会遇到一些问题。由于对COM编程了解得很少很少,有些问题我也没有找到很好的解决方法。

         一、ActiveX需要引用其他dll的问题

          我们的ActiveX需要对IC卡设备进行读写,所以需要调用设备自带的接口。设备厂商提供了“mwhrf_bj.lib”、“mwhrf_bj.dll”和“mwrf32.h”等接口文件。将“mwhrf_bj.lib”和“mwrf32.h”添加到项目中,ActiveX的接口方法中就可以调用接口文件中的方法了。但是在编译时会出现“Project:error PRJ0050:未能注册输出。请尝试启用“每个用户的重定向”,或用提升权限从命令提示窗口中注册该组件”或“Project : error PRJ0050: Failed to register output. Please ensure you have the appropriate permissions to modify the registry”的错误。

         实际上该错误不是出现在编辑阶段,而是出现在注册编译后的ocx文件时。Vs.net 2008默认在编译成功后会自动注册编译后的ocx文件。右击项目名称,选择“Properties”,在弹出对话框的“Configurations Properties->Linker->General”中的Register Output就可以配置编译后是否自动注册ocx,如下图所示:

           image

          之所以注册ocx时出错,是因为注册时找不到被调用的“mwhrf_bj.dll”文件。将被调用的“mwhrf_bj.dll”文件放在ocx文件相同目录下或者其他%PATH%路径下(如Windows文件夹或System32文件夹等),则注册ocx时不会报错。在vs.net开发环境中可以直接将要被调用的外部dll文件copy到Debug或Release目录下即可,也可以在PreBuild脚本里将外部dll文件COPY到编译目标文件夹,如:

           image

           注:可参考“http://www.cnblogs.com/lidabo/archive/2012/07/16/2593604.html”文章。

     

         二、ActiveX的调试方法

            在Vs.net 2008下可以对ActiveX按如下方式进行调试:

            1、准备好Demo.html文件并写好测试程序,该页面中需通过<object />来引用需测试的ocx控件(关于如何在html页面中调用控件在后续文章将专门提及)。

            2、在vs.net 2008中右击项目名称,选择“Properties”,在弹出框中的Debugging配置页里配置好CommandCommandArgs参数:

                Command:        本地IE浏览器的路径,如“C:\Program Files\Internet Explorer\IEXPLORE.EXE

                Command Args: 已经创建好的用于测试ocx的html文件路径(如上面提及的Demo.html文件路径)

                image

            3、在程序中需调试的地方设置断点。按F5运行后vs.net将自动启动IE并打开对应的html测试文件,在断点处会中断运行进入调试状态。

          三、ActiveX的接口实现out/ref参数及返回自定义结构体数据的问题

         有时候ActiveX的接口方法只返回一个数据并不能满足我们的实际要求。例如通过ActiveX的getPersons()方法返回一堆的人员信息,那必定是一个列表或数组,而且每个Person还包含姓名、性别等各种信息,这个时候返回值就相当复杂了。

         为了简单起见,还是已通过ActiveX进行读卡号来举例。一般情况下,只要该插件提供以下接口即可满足需求:

    BSTR ReadCardNo();

         这样在javascript中调用该ActiveX的ReadCardNo()方法即可返回一个包含卡号的字符串。

         但是,仅仅提供这个接口如何来识别读卡过程中出现的异常呢?如果读卡操作一切正常,返回一个卡号字符串当然没有问题。但如果读卡过程中出现诸如读卡设备未正确连接、卡无法识别等情况,如果将这些异常信息反馈给调用者呢?

         1、首先我想到的是使用ref或out参数来解决,对应C++里是OUT/RETVAL之类的参数修饰符。

         在.idl中定义接口为:

          [id(1), helpstring("方法ReadCardNo")] LONG GetSheetName([out]BSTR* cardNo);
         对应接口原型为:

          LONG ReadCardNo( BSTR* cardNo );

         这样的话通过LONG类型的返回值来识别返回状态,例如可以约定:

               0-读卡成功

               1-读卡设备未连接

               2-未找到可识别的卡

               ……

          如果返回值为0,表示读卡成功,读出的卡号已通过out类型的参数cardNo传递给调用者。

          但是,javascript等脚本语言并不支持out/ref等类型的参数,函数参数也无法传址,所以这个方案无法解决我的实际问题。

          2、如果ActiveX的接口能返回一个自定义的结构体类型数据就能满足我们的需求了。例如我们定义一个结构体:

              typedef struct

               {

                   LONG ResultStatus,              // 返回状态  0-读卡成功  1-读卡设备未连接 3-未找到可识别的卡

                   BSTR CardNo                       // 读卡成功时,保存读取的卡号

               } AOPResult;

              对应接口如果可以按如下样子来实现就可以解决我们的问题了:

              AOPResult ReadCardNo();

             但是,在MFC ACtiveX的接口定义中中不能直接使用自定义的数据类型的,需要用VARIANT类型来进行转换。下面几篇参考文章均对此有所描述:

              a) http://bbs.csdn.net/topics/320146859

              b) http://bbs.csdn.net/topics/20064135

              c) http://www.codeproject.com/Articles/916/Using-User-Defined-Types-in-COM-ATL

              d) 标准MFC WinSock ActiveX控件开发实例(II)高级篇

              但实现起来也不是那么容易,鉴于时间问题及我们实际需求的不迫切性,我对此没有做过多尝试。如果有成型实例,望请赐教。

           

          3、既然在Web应用场景下ActiveX的接口一般都是供js调用,那么我们可以返回一个json类型的数据即可,如“{ status:0, cardNo:234234344634 }”。这样ActiveX接口仍然只需返回一个BSTR的参数,只是返回值的意义变了,不是简单的卡号,而需要ActiveX的ReadCardNo接口在内部处理时需要将返回值封装成一个json格式的字符串返回并交由调用方解析。不过,在封装json字符串时需要对{、}、:等特殊字符进行相应处理。

          4、对于简单的应用场景,我们也完全可以利用ActiveX的属性来化解此类问题。例如我们在ActiveX中定义一个属性CardNo,这样的话提供的接口只用简单的返回一个状态即可:

             LONG ReadCardNo()

           接口返回值仍然表示状态,如0表示读卡成功,1表示未找到读卡设备等等。当返回0时,读卡成功,对应的卡号从属性CardNo中获取即可。

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    参考资料:

    ActiveX Controls( MFC )


    =======================================================================
    野文(Jasson Qian)
    ------------------------------------------------------
    博客园:http://qguohog.cnblogs.com
    CSDN:http://blog.csdn.net/sallay
  • 相关阅读:
    [CF1042F]Leaf Sets
    [CF1051F]The Shortest Statement
    [洛谷P1792][国家集训队]种树
    [CF484E]Sign on Fence
    [洛谷P2216][HAOI2007]理想的正方形
    [洛谷P4389]付公主的背包
    [洛谷P4726]【模板】多项式指数函数
    服务器上Ubuntu系统安装
    删除ubuntu系统
    Win10下安装Ubuntu16.04双系统
  • 原文地址:https://www.cnblogs.com/qguohog/p/2873655.html
Copyright © 2020-2023  润新知