• 开发ActiveX控件调用另一个ActiveX系列1——开发一个MFC ActiveX控件


    ActiveX开发的教程有很多,我也从中受益匪浅,例如以下这几篇:

    基本教程:http://www.cnblogs.com/guenli/articles/1629915.html

    注意事项:http://jon-lt.iteye.com/blog/1676272

    属性、方法开发:http://blog.csdn.net/waxgourd0/article/details/7652478

    但是由于我的目的是开发一个身份证识别仪的ActiveX控件,因此我就要先仿照识别仪ActiveX开发一个ActiveX。

    本文讲述如何模仿开发一个ActiveX控件,如果对此不感兴趣请阅读系列后续文章。

    我用vs2012,win8操作系统。

    新建MFC ActiveX控件工程

    image

    image

    我们选择ActiveX“运行时不可见”,“关于对话框随”便选不选都可以。项目生成后结构

    image

     

    建属性和方法

    根据身份证识别仪的测试页面,我们知道身份证的识别仪ActiveX必须有以下属性和方法

    var CVR_IDCard = document.getElementById("CVR_IDCard");                    
    var strReadResult = CVR_IDCard.ReadCard();
    if(strReadResult == "0"{
        ClearForm();
        document.all['Name'].value = CVR_IDCard.Name; 
        document.all['Sex'].value = CVR_IDCard.Sex;    
        document.all['Nation'].value = CVR_IDCard.Nation; 
        document.all['Born'].value = CVR_IDCard.Born; 
        document.all['Address'].value = CVR_IDCard.Address; 
        document.all['CardNo'].value = CVR_IDCard.CardNo; 
        document.all['IssuedAt'].value = CVR_IDCard.IssuedAt;  
        document.all['EffectedDate'].value = CVR_IDCard.EffectedDate;  
        document.all['ExpiredDate'].value = CVR_IDCard.ExpiredDate;
        document.all['SAMID'].value = CVR_IDCard.SAMID;
        document.all['pic'].src = CVR_IDCard.Pic;
        document.all['Picture'].value = CVR_IDCard.Picture;  
        document.all['PictureLen'].value = CVR_IDCard.PictureLen  
    }

    我们先建方法ReadCard,从方法上看,输入参数应该为空,返回值应该是个string。在“类视图”中选择如下路径,添加方法

    image

    image

    对于返回字符串的,我们选择BSTR类型,输入方法名,直接点完成即可。

    然后需要建Name、Nation、Born等方法,看来都是字符串类型即可。同样的路径,选择“添加属性”

    image

    类型仍然选择字符串BSTR,选择Get/Set方法,输入属性名Name

    image

    这时在ActiveXTestCtrl.cpp中就会有对应的属性和方法实现代码

    image

    我们在这里做一个最简单的实现,ReadCard直接返回0,GetName返回“Hello World”

    BSTR CActiveXTestCtrl::ReadCard(void)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
        CString strResult;
        strResult = "0";
        return strResult.AllocSysString();
    }
    
    
    BSTR CActiveXTestCtrl::GetName(void)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
        CString strResult;
        strResult = "Hello World";
        return strResult.AllocSysString();
    }
    
    
    void CActiveXTestCtrl::SetName(LPCTSTR newVal)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
        SetModifiedFlag();
    }

     

    生成测试

    打开ActiveXTest.idl文件,这个相当于dll中的def文件那样,会有很多控件的关键信息。包括接口、classid

    通过coclass是ActiveXTest,找到对应的classid是“AF7E1FF8-E4DC-47B8-BAC9-F06832ABB5F2

    //  CActiveXTestCtrl 的类信息
        [
            uuid(AF7E1FF8-E4DC-47B8-BAC9-F06832ABB5F2)
        ]
        coclass ActiveXTest
        {
            [default] dispinterface _DActiveXTest;
            [default, source] dispinterface _DActiveXTestEvents;
        };

    那么我们可以用原来识别仪驱动中带的测试页面,修改其中的classid为“AF7E1FF8-E4DC-47B8-BAC9-F06832ABB5F2”,就成为我们ActiveX控件的测试页了,代码如下

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <!-- saved from url=(0027)http://www.chinaidcard.com/ -->
    
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
        <title>华视电子CVR100B/S测试页</title>
    </head>
    <body style="text-align: center">
     <form id="form1" runat="server">    
        <OBJECT classid="clsid:AF7E1FF8-E4DC-47B8-BAC9-F06832ABB5F2"
          id="CVR_IDCard" name="CVR_IDCard" width="0" height="0" >
    </OBJECT>
    
                <script language="javascript" type ="text/javascript">
                        
    function ClearForm() {
                           document.all['Name'].value = ""; 
                           document.all['Sex'].value = ""; 
                           document.all['Nation'].value = ""; 
                           document.all['Born'].value = ""; 
                           document.all['Address'].value = ""; 
                           document.all['CardNo'].value = ""; 
                           document.all['IssuedAt'].value = ""; 
                           document.all['EffectedDate'].value = ""; 
                           document.all['ExpiredDate'].value = ""; 
                           document.all['SAMID'].value = ""; 
                           document.all['pic'].src = ""; 
                           document.all['Picture'].value = "";  
                           document.all['PictureLen'].value = "";     
                           return true;
    }
    function Button1_onclick() {
                        var CVR_IDCard = document.getElementById("CVR_IDCard");                    
                        var strReadResult = CVR_IDCard.ReadCard();
                        if(strReadResult == "0")
                        {
                            ClearForm();
                              document.all['Name'].value = CVR_IDCard.Name;  
                              document.all['Sex'].value = CVR_IDCard.Sex;    
                              document.all['Nation'].value = CVR_IDCard.Nation; 
                              document.all['Born'].value = CVR_IDCard.Born;     
                              document.all['Address'].value = CVR_IDCard.Address; 
                              document.all['CardNo'].value = CVR_IDCard.CardNo; 
                              document.all['IssuedAt'].value = CVR_IDCard.IssuedAt;  
                              document.all['EffectedDate'].value = CVR_IDCard.EffectedDate;  
                              document.all['ExpiredDate'].value = CVR_IDCard.ExpiredDate;
                              document.all['SAMID'].value = CVR_IDCard.SAMID;
                              document.all['pic'].src = CVR_IDCard.Pic;
                              document.all['Picture'].value = CVR_IDCard.Picture;  
                              document.all['PictureLen'].value = CVR_IDCard.PictureLen  
                          }
                          else
                          {
                            ClearForm();
                            alert(strReadResult);
                          }
                        
    }
    
    
    function Button3_onclick() {
                        var CVR_IDCard = document.getElementById("CVR_IDCard");                    
                        CVR_IDCard.AboutBox();
    
    }
    
                        </script>    
         &nbsp;华视电子CVR100 B/S 测试程序<table style=" 638px; height: 273px; border-top-style: groove; border-right-style: groove; border-left-style: groove; background-color: transparent; border-bottom-style: groove;">
             <tr>
                 <td style=" 98px">
                     姓名:</td>
                 <td style="text-align: left" colspan="3">
                     <input id="Text1" type="text" style=" 155px" name="Name" /></td>
                 <td style=" 138px; text-align: left;" rowspan="3">
                     <img  src="" style=" 91px; height: 108px" name="pic"/></td>
             </tr>
             <tr>
                 <td style=" 98px">
                     性别:</td>
                 <td style=" 80px">
                     <input id="Text2" type="text" name="Sex" style=" 154px" /></td>
                 <td style=" 58px">
                     民族:</td>
                 <td style=" 59px">
                     <input id="Text3" type="text" name="Nation" style=" 94px" /></td>
             </tr>
             <tr>
                 <td style=" 98px">
                     出生日期:</td>
                 <td style="text-align: left;" colspan="3">
                     <input id="Text4" type="text" style=" 151px" name="Born" /></td>
             </tr>
             <tr>
                 <td style=" 98px">
                     地址:</td>
                 <td colspan="4" style="text-align: left">
                     <input id="Text5" style=" 505px" type="text" name="Address" /></td>
             </tr>
             <tr>
                 <td style=" 98px">
                     身份号码:</td>
                 <td colspan="4" style="text-align: left">
                     <input id="Text6" style=" 506px" type="text" name="CardNo" /></td>
             </tr>
             <tr>
                 <td style=" 98px">
                     签发机关:</td>
                 <td colspan="4" style="text-align: left">
                     <input id="Text7" style=" 505px" type="text" name="IssuedAt" /></td>
             </tr>
             <tr>
                 <td style=" 98px">
                     有效期限:</td>
                 <td colspan="4" style="text-align: left">
                     <input id="Text8" style=" 163px" type="text" name="EffectedDate" /><input id="Text10" style=" 163px" type="text" name="ExpiredDate" /></td>
             </tr>
             <tr>
                 <td style=" 98px; text-align: left;">
                     模块号码:</td>
                 <td colspan="4" style="text-align: left">
                     <input id="Text9" style=" 506px" type="text" name="SAMID" /></td>
             </tr>
             <tr>
                 <td style=" 98px; text-align: left; height: 136px;">
                     照片编码:</td>
                 <td colspan="4" style="text-align: left; height: 136px;">
                     <textarea id="TextArea1" name="Picture" style=" 509px; height: 115px"></textarea></td>
             </tr>
             <tr>
                 <td style=" 98px; text-align: left">
                     编码长度:</td>
                 <td colspan="4" style="text-align: left">
                     <input id="Text11" style=" 508px" type="text" name="PictureLen"/></td>
             </tr>
         </table>
                            
                                            
                
        </form>
        &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
        &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
        &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
        &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
        &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<input id="Button1" type="button" value="读   卡" onclick="return Button1_onclick()" />
        &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
        &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
        &nbsp; &nbsp; &nbsp; &nbsp;<input id="Button3" type="button" value="关   于" onclick="return Button3_onclick()" />
        &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
        &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
        &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
        &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
    
    </body>
    </html>

    编译项目,如果出现以下错误,别担心,不是代码问题,是因为VS没有权限注册ActiveX控件到注册表

    image

    警告    1    warning MSB3075: 命令“regsvr32 /s "f:ActiveXTestActiveXTestDebugActiveXTest.ocx"”已退出,代码为 5。请验证您是否有足够的权限来运行此命令。    C:Program Files (x86)MSBuildMicrosoft.Cppv4.0V110Microsoft.CppCommon.targets    1609    5    ActiveXTest

    错误    2    error MSB8011: Failed to register output. Please try enabling Per-user Redirection or register the component from a command prompt with elevated permissions.    C:Program Files (x86)MSBuildMicrosoft.Cppv4.0V110Microsoft.CppCommon.targets    1621    5    ActiveXTest

    我们访问生成目录

    新建一个脚本setup.bat

    cd /d "%~dp0"
    regsvr32.exe ActiveXTest.ocx

    然后右键,以管理员身份运行

    image

    这样就注册成功了

    image

    我们还可以进入注册表regedit.exe,查看HKEY+CLASSES_ROOTWow6432Node(不同操作系统这里不一样)CLSID

    {AF7E1FF8-E4DC-47B8-BAC9-F06832ABB5F2}中,看到这个ID已经对应磁盘上对应路径的ocx文件了。

    image

    运行

    如果是VS2010开发,则至此可以运行测试。但是VS2012开发的项目,仍需要做一些加工——在代码中实现IObjectSafety接口,参见如下:

    用VS2012做MFC ActiveX控件并使用html、c#、c++测试容器:http://blog.csdn.net/zengraoli/article/details/17019513

    编译后,打开上面准备好的“测试页.html”,点击“读卡”按钮后则显示了Hello World,用同样的方式实现其他属性。

    image

    至此,我们就实现了一个高仿的身份证识别仪读取ActiveX控件。

    如果要伪造身份证识别仪读取结果,欺骗业务系统说数据是身份证识别仪读入的,只需要修改相关GUID。后面再说就太危险了,怕查水表,就不深入了。

    附代码:代码

  • 相关阅读:
    java基础教程-流IO(五)
    java基础教程-常用类(四)
    java基础教程-容器(三)
    java基础教程-异常处理(二)
    java基础教程-面向对象(一)
    javascript DOM编程艺术(笔记)
    二十二、动态规划
    二十一、所有结点对最短路径问题(弗洛伊德算法)
    二十、单源最短路径(迪杰斯特拉算法)
    十九、最小生成树(普里姆算法)
  • 原文地址:https://www.cnblogs.com/anic/p/5014643.html
Copyright © 2020-2023  润新知