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

一.前言

本文将采用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 begin
BEGIN_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 off
set fileName=XXX.ocx
if exist %windir%\SysWOW64 (goto x64) else (goto x86)

:x64
set sys=SysWOW64
set dir=%WINDIR%\%sys%\
set cmd=%dir%%fileName%
xcopy /y "%~dp0%fileName%" "%dir%"
regsvr32 %cmd%
exit


:x86
set sys=System32
set 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,选择路径解压后即可自动注册!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值