VC6.0 MFC创建OCX入门-详细完整流程(JS调用测试, 去除安全提示, exe打包)

来源:互联网 发布:数据挖掘招聘要求 编辑:程序博客网 时间:2024/05/16 14:49

一.前言

本文将采用VC6.0 MFC创建OCX, OCX提供两个简单接口供JS在网页中调用,分别是:

  1. Long AddNumber(Long, Long):返回数字相加之和, 整形传入传出.
  2. BSTR AddString(LPCTSTR, LPCTSTR):返回字符串拼接结果, 字符串传入传出.

二.VC6.0制作OCX

  1. 创建工程:输入工程名ocxTest, 点OK, 接下来选择默认选项直到完成.
  2. 添加方法:
    打开类视图, 选择此处并鼠标单击右键

    1. 添加Long AddNumber(Long, Long)方法:
      按图所示输入名称, 传入, 传出参数
    2. 添加BSTR AddString(LPCTSTR, LPCTSTR)方法:
      按图所示输入名称, 传入, 传出参数
    3. 添加方法后, VC3个文件共4处新增了代码, 不关注文档结构的同学此处可略过.
      1. ocxTest.odl文件:
        这里写图片描述
      2. OcxTestCtl.h文件:
        这里写图片描述
      3. OcxTestCtl.cpp文件上方:(该文件还有一处改动在下方, 就是我们一会要为方法添加代码的地方, 详见下一步此处略.)
        这里写图片描述
  3. 为方法添加代码:
    这里写图片描述

  4. 生成OCX并注册:
    1. 点击Build->Rebuild All生成ocxTest.ocx.
    2. 注册:将ocx根据操作系统位数放到对应目录,
      32位放到C:\Windows\System32,64位放到C:\Windows\SysWOW64;
      我的是64然后以管理员身份打开CMD窗口运行命令:regsvr32 C:\Windows\SysWOW64\ocxTest.ocx

三.JS调用

  1. 调用说明:
    以下代码需保存在以.html为后缀的文件,并修改OBJECT标签下的CLASSID;
    CLASSID是每个OCX独有的, 它的值存在ocxTest.odl文件最下方的uuid(5E5397D6-B705-49C2-A6AF-7EA9F036F206)括号内;
    ID=”myocx”, 这个ID值可以是任意名字, 用来标识OCX对象, 在JS函数调用时使用.
<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=gb2312"/><TITLE>Add Func Test</TITLE><script language="javascript" type="text/javascript">function Button1_onclick() {    var num1 = form1.Num1.value;    var num2 = form1.Num2.value;    try{        var result = myocx.AddNumber(num1, num2);        alert(result);    }    catch(e){        alert(e.name + ": " + e.message);    }}function Button2_onclick() {    var str1 = form1.Str1.value;    var str2 = form1.Str2.value;    try{        var result = myocx.AddString(str1, str2);        alert(result);    }    catch(e){        alert(e.name + ": " + e.message);    }}</script></HEAD><BODY><OBJECT ID="myocx" CLASSID="CLSID:5E5397D6-B705-49C2-A6AF-7EA9F036F206"></OBJECT><form id="form1">    Num1: <input name="Num1" id="Num1" type="text" size=20><br/>    Num2: <input name="Num2" id="Num2" type="text" size=20><br/>    <input id="Button1" type="button" value="AddNumber" onclick="return Button1_onclick()" /><br/><br/>    Str1: <input name="Str1" id="Str1" type="text" size=20><br/>    Str2: <input name="Str2" id="Str2" type="text" size=20><br/>    <input id="Button2" type="button" value="AddString" onclick="return Button2_onclick()" /> </form></BODY></HTML>
  • 调用结果:
    注:请用IE打开, 如果网页无法打开, 在工具->internet选项中将127.0.0.1加入受信任的站点, 并在自定义级别中将activeX启用.
    这里写图片描述
    这里写图片描述

四.去除网页安全提示

  • 说明:
    网页打开后的会有如下安全提示, 不介意的同学可忽略此步.
    这里写图片描述
  • 在XXXCtrl.h中:(XXX为工程名)
1.添加头文件:#include <objsafe.h>
2.在class COcxTestCtrl{}中添加以下代码:
//safety begin    DECLARE_INTERFACE_MAP()       BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)//去IE安全检测          STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) (//去IE安全检测              REFIID riid,  DWORD __RPC_FAR *pdwSupportedOptions, DWORD __RPC_FAR *pdwEnabledOptions);         STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) (//去IE安全检测              REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions);      END_INTERFACE_PART(ObjSafe);//去IE安全检测     //safety end
  • 在OcxTestCtl.cpp中添加以下代码:
//safety beginBEGIN_INTERFACE_MAP(COcxTestCtrl, COleControl)   INTERFACE_PART(COcxTestCtrl, IID_IObjectSafety, ObjSafe)  END_INTERFACE_MAP()  /////////////////////////////////////////////////////////////////////////////  // IObjectSafety member functions  // Delegate AddRef, Release, QueryInterface  ULONG FAR EXPORT COcxTestCtrl::XObjSafe::AddRef()  {      METHOD_PROLOGUE(COcxTestCtrl, ObjSafe)      return pThis->ExternalAddRef();  }  ULONG FAR EXPORT COcxTestCtrl::XObjSafe::Release()  {      METHOD_PROLOGUE(COcxTestCtrl, ObjSafe)      return pThis->ExternalRelease();  }  HRESULT FAR EXPORT COcxTestCtrl::XObjSafe::QueryInterface(      REFIID iid, void FAR* FAR* ppvObj)  {      METHOD_PROLOGUE(COcxTestCtrl, ObjSafe)      return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);  }  const DWORD dwSupportedBits =    INTERFACESAFE_FOR_UNTRUSTED_CALLER |    INTERFACESAFE_FOR_UNTRUSTED_DATA;  const DWORD dwNotSupportedBits = ~dwSupportedBits;  /////////////////////////////////////////////////////////////////////////////  // CXXXCtrl::XObjSafe::GetInterfaceSafetyOptions  // Allows container to query what interfaces are safe for what. We're  // optimizing significantly by ignoring which interface the caller is  // asking for.  HRESULT STDMETHODCALLTYPE COcxTestCtrl::XObjSafe::GetInterfaceSafetyOptions(          REFIID riid,          DWORD __RPC_FAR *pdwSupportedOptions,          DWORD __RPC_FAR *pdwEnabledOptions)  {      METHOD_PROLOGUE(COcxTestCtrl, ObjSafe)      HRESULT retval = ResultFromScode(S_OK);      // does interface exist?      IUnknown FAR* punkInterface;      retval = pThis->ExternalQueryInterface(&riid,                                            (void **)&punkInterface);      if(retval != E_NOINTERFACE)      { // interface exists          punkInterface->Release(); // release it--just checking!      }      // we support both kinds of safety and have always both set,      // regardless of interface      *pdwSupportedOptions = *pdwEnabledOptions = dwSupportedBits;      return retval; // E_NOINTERFACE if QI failed  }  /////////////////////////////////////////////////////////////////////////////  // CXXXCtrl::XObjSafe::SetInterfaceSafetyOptions  // Since we're always safe, this is a no-brainer--but we do check to make  // sure the interface requested exists and that the options we're asked to  // set exist and are set on (we don't support unsafe mode).  HRESULT STDMETHODCALLTYPE COcxTestCtrl::XObjSafe::SetInterfaceSafetyOptions(          REFIID riid,          DWORD dwOptionSetMask,          DWORD dwEnabledOptions)  {      METHOD_PROLOGUE(COcxTestCtrl, ObjSafe)      // does interface exist?      IUnknown FAR* punkInterface;      pThis->ExternalQueryInterface(&riid, (void **)&punkInterface);      if(punkInterface)      { // interface exists          punkInterface->Release(); // release it--just checking!      }      else       { // interface doesn't exist          return ResultFromScode(E_NOINTERFACE);      }      // can't set bits we don't support      if(dwOptionSetMask & dwNotSupportedBits)       {          return ResultFromScode(E_FAIL);      }      // can't set bits we do support to zero      dwEnabledOptions &= dwSupportedBits;      // (we already know there are no extra bits in mask )      if((dwOptionSetMask & dwEnabledOptions) != dwOptionSetMask)       {          return ResultFromScode(E_FAIL);      }             // don't need to change anything since we're always safe      return ResultFromScode(S_OK);  } //safety end
  • 最后, 重新编译注册即可.

五.打包成exe安装包

  • 说明:
    安装包的作用是, 在执行以后将自动根据操作系统位数,将ocx文件拷贝到系统对应目录(system32 or SysWOW64), 并执行注册.

  • 步骤:
    1.准备材料:
    (1).ocx文件
    (2).register.bat文件
    新建文件, 将文件名改为register.bat并写入以下内容:
    只需将set fileName=后面改为实际的ocx文件名.

@echo offset fileName=XXX.ocxif exist %windir%\SysWOW64 (goto x64) else (goto x86):x64set sys=SysWOW64set dir=%WINDIR%\%sys%\set cmd=%dir%%fileName%xcopy /y "%~dp0%fileName%" "%dir%"regsvr32 %cmd%exit:x86set sys=System32set dir=%WINDIR%\%sys%\set cmd=%dir%%fileName%xcopy /y "%~dp0%fileName%" "%dir%"regsvr32 %cmd%exit
  • 用好压选中上述两个文件打包为setup.zip:

  • 双击setup.zip, 选择自解压->解压标签:
    在解压后运行一栏写入:.\register.bat
    点确定即可生成setup.exe文件
    这里写图片描述

  • 最后, 以管理员身份运行setup.exe,选择路径解压后即可自动注册!

原创粉丝点击