VS2010下ocx开发三部曲

目录

一、用C++ MFC ActiveX开发简单的ocx控件

二、在C#程序中调用ocx控件

三、在Web页面中调用已实现的ocx控件

四、OCX、COM的区别以及C++、C#和VB开发的组件的区别

1.什么是OCX?

2.OCX、COM的区别以及C++、C#和VB开发的组件的区别?

3.C#开发COM组件需要选择的项目?

4.开发结束后对外开放的接口如何提供给HTML使用?

5.MFC OCX控件实现安全初始化和脚本安全的方法

6.查看ocx或dll文件依赖项列表的方法


一、用C++ MFC ActiveX开发简单的ocx控件

本文给出了在Visual Studio 2010开发环境下使用向导工具生成一个简单ocx控件的示例。

    首先以管理员身份运行Visual Studio 2010,这样做的目的是在将来编译控件时VS2010能自动注册ocx控件,不会出现权限不足导致失败的错误。如果不使用管理员身份运行VS 2010,将来就需要使用regsvr32命令手动注册创建的ocx控件(注意执行regsvr32命令时也要使用管理员身份,即以管理员身份执行cmd.exe,然后在命令行窗口中执行regsvr32命令)。在“起始页”中点击“新建项目”,就会弹出对话框,如下图所示:

    将要创建一个做乘法运算的ocx控件,于是给项目起名叫"MultiplyDemo",点击”确定“按钮,接下来向导显示如下:

    接下来都采用默认设置,连续点击”下一步“按钮,显示依次如下:

    这里勾选了“运行时不可见”和”有‘关于’对话框“这两项,点击”完成“按钮,将会自动创建相关的文件。完成后切换到”类视图“,展开MultiplyDemoLib这一项,在下属的_DMultiplyDemo这一项上点击鼠标右键,在弹出菜单选项中点击”添加方法“,如下图:

    在”添加方法向导“对话框中,方法名设为”Multiply“,返回类型在下拉列表中选中LONG。在“参数类型”下拉列表中选择LONG,“参数名”输入框中输入Num1,点“添加”按钮添加一个参数Num1,再按同样方法添加参数Num2,如下图:

    点击“下一步”按钮,显示如下:

    不修改默认设置,点击“完成”按钮。接下来按Ctrl+F快捷键,搜索Multiply,定位到MultiplyDemoCtrl.cpp文件中Multiply(LONG Num1, LONG Num2)方法的定义部分,如下图:

    修改Multiply( )函数的定义,改为如下:

    即该函数的返回值是两个输入参数Num1与Num2的乘积。

    在“解决方案资源管理器”窗口中,在MultiplyDemo这一项上点击鼠标右键,点击“生成”选项,如下图:

    完成之后,到程序所在目录下,可以看到创建了MultiplyDemo.ocx文件,如下图:

    可以使用COMRaider工具软件(网址:https://github.com/dzzie/COMRaider)查看一下生成的ocx文件,显示如下:

    可以看到在MultiplyDemo.ocx控件中包含了一个名为Multiply的方法。

二、在C#程序中调用ocx控件

在本文中,给出一个C#示例程序,调用上一篇博文中创建的MultiplyDemo.ocx控件。注意需要保证该控件已经注册过。

    启动Visual Studio 2010,使用C#创建一个Windows窗体程序,如下图:

    点击“确定”按钮之后,就自动创建了项目和相关文件,如下图:

    从工具箱中向窗体上拖拽5个Label控件,Text属性值分别为“计算两个整数的乘积”、“整数1:”、“整数2:、“乘积:”,注意最后一个Label控件Lable5的Text属性值为空,将来会用它显示乘积。从工具箱中向窗体上拖拽两个Button控件,Text属性值分别为“计算乘积”、“退出”。从工具箱中向窗体上拖拽两个TextBox控件,分别放在Label“整数1:”、“整数2:”的右侧。在“解决方案资源管理器”子窗口中,在“引用”这一项上点击鼠标右键,在弹出选项中点击“添加引用”,如下图所示:

    在弹出的对话框中,选择在上一篇博文中创建的控件MultiplyDemoLib,如下图:

    点击“确定”按钮。

    接下来按Ctrl+Alt+x组合键,调出“工具箱”子窗口,在子窗口中点击鼠标右键,在弹出菜单中选择“选择项”,如下图:

    在弹出对话框中的“COM组件”标签页中,选中创建的MultiplyDemo Control,点击“确定”按钮,如下图:

    将会发现在“工具箱”子窗口中的“常规”项目下面,多出来一项MultiplyDemo Control,如下图:

    点击“工具箱”中的MultiplyDemo Control,将它拖拽到窗体上,如下图:

    为两个Button控件填写Click事件处理代码,如下图:

    按F5键,执行程序,显示如下:

    在两个TextBox中输入数字,点击“计算乘积”按钮,即可看到乘积的值,如下图:

    点击“退出”按钮,即可退出程序。

    ocx控件中还包含了AboutBox( )方法,为了调用该方法,可以往窗体上再拖拽一个Button控件,Text属性值设为“显示控件自带对话框”。该Button的Click事件处理代码如下:

     执行程序,点击“显示控件自带对话框”按钮,如下图:

    显示结果如下:

三、在Web页面中调用已实现的ocx控件

打开在博文:http://blog.csdn.net/henter/article/details/79399986 中创建的 MultiplyDemo 项目,在“解决方案资源管理器”窗口中双击 MultiplyDemo.idl 文件,在该文件中找到“CMultiplyDemoCtrl 的类信息”这一段内容,将其中的uuid后面括号中的内容保存下来,后面将会用到。如下图:

    写一个名为index.html的文件,内容如下:

<!DOCTYPE html>

<html>

<body>

<OBJECT id="MultiplyDemo" classid="clsid:526453C4-2FC0-4196-99BC-3B0D223BE780" width="0" height="0">

</OBJECT>

<h1>调用乘法控件演示页面</h1>

<p>请输入数字</p>

<p>x = <input id="num1" type="text"></p>

<p>y = <input id="num2" type="text"></p>

<p id="productText">结果将显示在这里......</p>

<script>

function computProduct()

{

var num01=document.getElementById("num1").value;

if (num01=="" || isNaN(num01))

{

alert("输入错误!不是整数")

return;

}


var num02=document.getElementById("num2").value;

if (num02=="" || isNaN(num02))

{

alert("输入错误!不是整数")

return;

}


var multiplyOcx=document.getElementById("MultiplyDemo")

if (multiplyOcx)

{

var productResult = multiplyOcx.Multiply(num01, num02);

document.getElementById("productText").innerHTML = num01.toString() + "*" + num02.toString() + "= " + productResult.toString();

}

else

{

alert("控件不存在!");

}

}


function showOcxAboutBox()

{

var multiplyOcx=document.getElementById("MultiplyDemo")

if (multiplyOcx)

{

multiplyOcx.AboutBox();

}

else

{

alert("控件不存在!");

}

}


</script>


<button type="button" οnclick="computProduct()">计算乘积</button>

<p></p>

<button type="button" οnclick="showOcxAboutBox()">显示控件自带的对话框</button>

</body>

</html>

    注意 html 文件中的 classid="clsid:526453C4-2FC0-4196-99BC-3B0D223BE780" ,这里用到了前面保存的 uuid 值。

    将 index.html 和 MultiplyDemo.ocx 文件放到同一个目录下,使用IE打开保存在本机磁盘上的 index.html 文件,显示如下:

    点击下方的“允许阻止的内容”,将弹出如下对话框:

    点击“是”按钮后,页面显示如下:

    在输入框中分别输入两个整数值,点击“计算乘积”按钮,页面显示类似下图:

    如果点击“显示控件自带的对话框”按钮,页面显示如下:

    如果html文件调用ocx文件失败,可以从以下方面查找原因:

1)ocx控件是否已被注册过?

2)系统中是否包括一些必要的库文件,比如VS 2010相关的动态库。为了减轻对库文件的依赖,在编译ocx控件时,可以按下图设置:

    这样编译出来的ocx文件的体积虽然会增大一些,但是可以减轻对库文件的依赖。

    上面介绍了在本地磁盘上的html文件中调用已实现的ocx控件,接下来将index.html文件放到Web服务器上。为了简单,这里使用一个轻量级的Web服务器软件 Abyss Web Server X1,其官网地址是 http://aprelium.com/abyssws/ 。安装该软件后,将index.html 和 MultiplyDemo.ocx 这两个文件拷贝到 \Abyss Web Server\htdocs 目录下,启动 IE 浏览器,将 http://localhost 添加到受信任的站点,如下图所示:

  在“开始”菜单中点击 Abyss Web Server X1 软件图标,启动该 Web 服务器,如下图:

   打开 IE 浏览器,输入网址:http://localhost/index.html ,显示如下:

    在输入框中随意分别输入两个整数值,点击“计算乘积”按钮及点击“显示控件自带的对话框”按钮,页面显示如下:

    如果不将 http://localhost 添加到 IE 的受信任站点,使用 IE 浏览器时,在“Internet选项”->“高级”中如果勾选了“禁用脚本调试(Internet Explorer)”,那么点击网页上的按钮时,将无任何反应。如果取消了对“禁用脚本调试(Internet Explorer)”的勾选,如下图:

    点击网页上的按钮时,会出现如下错误提示:

    导致这个错误的原因是在编程实现ocx控件时,没有相关的安全接口,因此IE阻止了对该控件的调用。对于实现安全接口的方法,可以参考以下链接:
https://support.microsoft.com/en-us/help/161873/how-to-mark-mfc-activex-controls-as-safe-for-scripting-and-initializat
http://www.cnblogs.com/qguohog/archive/2013/01/22/2871805.html

    这里介绍一下实现过程。首先以管理员身份启动VS 2010,打开项目 MultiplyDemo,在“解决方案资源管理器”窗口中,在“头文件”下添加一个名为Cathelp.h的文件,内容如下:

#include "comcat.h"
 
// Helper function to create a component category and associated
// description
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription);
 
// Helper function to register a CLSID as belonging to a component
// category
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid);
 
// HRESULT UnRegisterCLSIDInCategory - Remove entries from the registry 
HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid);

    在“源文件”下添加一个名为Cathelp.cpp的文件,内容如下:

#include "stdafx.h"
#include "comcat.h"
#include "strsafe.h"
#include "objsafe.h"
 
 
// HRESULT CreateComponentCategory - Used to register ActiveX control as safe 
HRESULT CreateComponentCategory(CATID catid, WCHAR *catDescription)
{
    ICatRegister *pcr = NULL ;
    HRESULT hr = S_OK ;
 
    hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
    if (FAILED(hr))
        return hr;
 
    // Make sure the HKCR\Component Categories\{..catid...}
    // key is registered.
    CATEGORYINFO catinfo;
    catinfo.catid = catid;
    catinfo.lcid = 0x0409 ; // english
    size_t len;
    // Make sure the provided description is not too long.
    // Only copy the first 127 characters if it is.
    // The second parameter of StringCchLength is the maximum
    // number of characters that may be read into catDescription.
    // There must be room for a NULL-terminator. The third parameter
    // contains the number of characters excluding the NULL-terminator.
    hr = StringCchLength(catDescription, STRSAFE_MAX_CCH, &len);
    if (SUCCEEDED(hr))
        {
        if (len>127)
          {
            len = 127;
          }
        }   
    else
        {
          // TODO: Write an error handler;
        }
    // The second parameter of StringCchCopy is 128 because you need 
    // room for a NULL-terminator.
    hr = StringCchCopy(catinfo.szDescription, len + 1, catDescription);
    // Make sure the description is null terminated.
    catinfo.szDescription[len + 1] = '\0';
 
    hr = pcr->RegisterCategories(1, &catinfo);
    pcr->Release();
 
    return hr;
}
 
// HRESULT RegisterCLSIDInCategory -
//      Register your component categories information 
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
// Register your component categories information.
    ICatRegister *pcr = NULL ;
    HRESULT hr = S_OK ;
    hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
                NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
    if (SUCCEEDED(hr))
    {
       // Register this category as being "implemented" by the class.
       CATID rgcatid[1] ;
       rgcatid[0] = catid;
       hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
    }
 
    if (pcr != NULL)
        pcr->Release();
            
    return hr;
}
 
// HRESULT UnRegisterCLSIDInCategory - Remove entries from the registry 
HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
    ICatRegister *pcr = NULL ;
    HRESULT hr = S_OK ;
 
    hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
    if (SUCCEEDED(hr))
    {
       // Unregister this category as being "implemented" by the class.
       CATID rgcatid[1] ;
       rgcatid[0] = catid;
       hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
    }
 
    if (pcr != NULL)
        pcr->Release();
 
    return hr;
}

    在“解决方案资源管理器”子窗口中,双击“源文件”下面的 MultiplyDemoCtrl.cpp,打开该文件后,找到下面的内容:

    将以下内容记录下来:
// 初始化类工厂和 guid

IMPLEMENT_OLECREATE_EX(CMultiplyDemoCtrl, "MULTIPLYDEMO.MultiplyDemoCtrl.1",
0x526453c4, 0x2fc0, 0x4196, 0x99, 0xbc, 0x3b, 0xd, 0x22, 0x3b, 0xe7, 0x80)

    在“解决方案资源管理器”子窗口中,双击“源文件”下面的 MultiplyDemo.cpp,打开该文件,编写下面一段代码:
const CATID CLSID_SafeItem = {0x526453c4, 0x2fc0, 0x4196,{0x99, 0xbc, 0x3b, 0xd, 0x22, 0x3b, 0xe7, 0x80}};
 

    注意:花括号中的数值来源于刚才复制的内容,并加以修改,即前三个值不变,后面8个值再放入到一个花括号中。将这一段代码粘贴到 MultiplyDemoCtrl.cpp 文件中 CMultiplyDemoApp theApp; 这一行后面,如下图:

    在 MultiplyDemo.cpp 文件起始处,加入下面两行代码:

#include "Cathelp.h"

#include "objsafe.h"

如下图:

    在 MultiplyDemo.cpp 文件中,找到 DllRegisterServer( ) 和 DllUnregisterServer( )两个函数,删除它们。粘贴下面的代码:

// DllRegisterServer - Adds entries to the system registry
 
STDAPI DllRegisterServer(void)
{
    HRESULT hr;    // HResult used by Safety Functions
 
    AFX_MANAGE_STATE(_afxModuleAddrThis);
 
    if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
      return ResultFromScode(SELFREG_E_TYPELIB);
 
    if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
      return ResultFromScode(SELFREG_E_CLASS);
 
    // Mark the control as safe for initializing.
                                             
    hr = CreateComponentCategory(CATID_SafeForInitializing, 
         L"Controls safely initializable from persistent data!");
    if (FAILED(hr))
      return hr;
 
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, 
         CATID_SafeForInitializing);
    if (FAILED(hr))
        return hr;
 
    // Mark the control as safe for scripting.
 
    hr = CreateComponentCategory(CATID_SafeForScripting, 
                                 L"Controls safely  scriptable!");
    if (FAILED(hr))
        return hr;
 
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, 
                        CATID_SafeForScripting);
    if (FAILED(hr))
        return hr;
 
    return NOERROR;
}
 
 
 
// DllUnregisterServer - Removes entries from the system registry
 
STDAPI DllUnregisterServer(void)
{
    AFX_MANAGE_STATE(_afxModuleAddrThis);  
 
    // 删除控件初始化安全入口.   
    HRESULT hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);  
 
    if (FAILED(hr))  
        return hr;  
 
    // 删除控件脚本安全入口   
    hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);  
 
    if (FAILED(hr))  
        return hr;  
 
    if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))  
        return ResultFromScode(SELFREG_E_TYPELIB);  
 
    if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))  
        return ResultFromScode(SELFREG_E_CLASS);  
 
    return NOERROR;
}

    在“解决方案资源管理器”子窗口中,右键单击“资源文件”下面的 MultiplyDemo.rc,在弹出菜单中选择“查看代码”,如下图所示:

    找到“BLOCK "StringFileInfo"”这一行,从这一行开始向下看,
1)将BLOCK的值设为:"040904e4"
2)将OLESelfRegister的值设为:"\0"

3)"Translation"后面改为:0x0409, 1252。修改如下图所示:

    重新生成 MultiplyDemo.ocx 等文件。将该文件拷贝到 Abyss Web Server X1 服务器软件的  \Abyss Web Server\htdocs 目录下,覆盖原有的同名文件。重启一下 Abyss Web Server X1 服务器软件,启动 IE 浏览器,输入网址:http://localhost/index.html (注意:当前未将 http://localhost 加入 IE 的受信任站点),在页面上的输入框中分别随意输入两个整数,点击“计算乘积”按钮及点击“显示控件自带的对话框”按钮,页面显示如下:

 此时点击网页上的按钮,能够执行对应的功能。 建议如果有条件的话,最好对 MultiplyDemo.ocx 文件进行数字签名。

四、OCX、COM的区别以及C++、C#和VB开发的组件的区别

参考:关于C#开发OCX组件的说明_zms19841230的博客-CSDN博客_c# ocx

1.什么是OCX?

OCX是指用C++、C#或者VB开发的COM组件,对外开放的接口可提供和html进行调用,解决html调用本地电脑资源或者第三方集成的问题。应用场景包括银行、视频播放(用flash也能解决相关问题)等。

2.OCX、COM的区别以及C++、C#和VB开发的组件的区别?

对于HTML调用的组件来说,OCX和COM没有任何区别,用C++和VB开发可以生成OCX或COM组件,但是用C#只能生成COM组件。

C#是微软的产物,所以其生成的COM组件目前只能提供给IE使用;

OCX同样支持IE,但是在也可以开发出非IE内核使用;

3.C#开发COM组件需要选择的项目?

对于windows开发而言,实质上开发COM就是开发DLL,选择C#开发基本上都是使用Virual Studio(我使用的是VS2008,.NET版本是3.5),新建项目选择类库即可。

4.开发结束后对外开放的接口如何提供给HTML使用?

想要使DLL能为COM组件在程序里需要对AssemblyInfo.cs(Android开发同事可以将其理解为Android里面的AndroidManifest.xml)文件添加[assembly: Guid("151e5c23-d121-4f26-a035-7a43f6d775b0")],表示此项目向COM公开,GUID用于类型库;

在开放接口类里面实现IObjectSafety接口(实现代码不用改,网上都是一样的,直接拿过来就行);

最后在你的开放接口类外部添加自定义GUID,这是最关键的一步,[GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967")],这个GUID需要自己生成,HTML的开发者在集成安装你提供的COM组件后需要知道你的GUID,才能正常使用你提供的接口;

HTML里面先加载COM组件(注意:这里对于HTML而言不关注OCX或者COM里,调用方法一样),<objectid="YouOcx"classid="clsid:FD05F7D5-BA6A-4d6a-9F79-DFADB79BA2B0"></object>, 这里的classid就是你开发COM组件所 使用的GUID,然后在html里面就可以使用该对象了,varocx = document.getElementById("YouOcx ");

ocx.XXX();,这里的XXX()就是你COM所提供给HTML调用的方法。

5.MFC OCX控件实现安全初始化和脚本安全的方法

两种方法:

方法1:通过IObjectSafety接口实现(推荐)

方法2:通过代码修改注册表实现

参考:添加IObjectSafety接口使MFC写的OCX可信_smilingc_开发小记-CSDN博客

感谢此篇博客。找了很久没有找到IObjectSafety需要添加哪些代码,这篇代码很详细。
MFC OCX控件实现安全初始化和脚本安全的方法

原文有两个方法,我更推荐用IObjectSafety,原博客的代码不太好看,我这里整理一下。
我的环境是VS2013,用模板生成的项目包含的文件基本相同,不构成影响。一般如下结构:
模板

假定我们用模板生成的项目名叫[TestOCX],所以马赛克部分应该都是TestOCX。相应的,本文涉及的两个文件分别为TestOCXCtrl.h和TestOCXCtrl.cpp。 如果需要,则请将代码中的TestOCXCtrl替换成各位自己的名字。

  1. TestOCXCtrl.h添加如下代码
#include <objsafe.h> // for IObjectSafety; in ActiveX SDK

这个代码是实现IObjectSafety的前提。

  1. 依然是在TestOCXCtrl.h中,一般在类的构造函数前有一行
DECLARE_DYNCREATE(CTestOCXCtrl)

在这行代码前添加如下代码:


#pragma region objsafe
//*******************************************************add begin
    //ISafeObject
    DECLARE_INTERFACE_MAP()
    BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)

    STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) (
    /* [in] */ REFIID riid,
    /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
    /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions
    );

    STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) (
        /* [in] */ REFIID riid,
        /* [in] */ DWORD dwOptionSetMask,
        /* [in] */ DWORD dwEnabledOptions
        );
    END_INTERFACE_PART(ObjSafe);

    //ISafeObject
//*******************************************************add end

#pragma endregion

加上#pragma region objsafe只是因为方便折叠…

  1. TestOCXCtrl.cpp中,注意替换下述代码中所有CTestOCXCtrl为自己控件的名称。需要添加的有几个位置
    (1)消息映射内添加如下代码
BEGIN_MESSAGE_MAP(CTestOCXCtrl, COleControl)
    //下面是要添加的
    //{{AFX_MSG_MAP(CTestOCXCtrl)
    // NOTE - ClassWizard will add and remove message map entries
    //    DO NOT EDIT what you see in these blocks of generated code !
    //}}AFX_MSG_MAP
    ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
    //添加结束
END_MESSAGE_MAP()

(2)紧跟其后如果没有接口映射的话,下述代码完整添加;否则添加接口映射内即可

//*******************************************************add begin
BEGIN_INTERFACE_MAP(CTestOCXCtrl, COleControl)
    INTERFACE_PART(CTestOCXCtrl, IID_IObjectSafety, ObjSafe)
END_INTERFACE_MAP()
//*******************************************************add end

(3)在文件末尾完整复制粘贴如下代码

增加IObjectSafety接口实现方法
***************************************************************add begin

// IObjectSafety member functions

// Delegate AddRef, Release, QueryInterface

ULONG FAR EXPORT CTestOCXCtrl::XObjSafe::AddRef()

{

    METHOD_PROLOGUE(CTestOCXCtrl, ObjSafe)

    return pThis->ExternalAddRef();

}

ULONG FAR EXPORT CTestOCXCtrl::XObjSafe::Release()

{

    METHOD_PROLOGUE(CTestOCXCtrl, ObjSafe)

    return pThis->ExternalRelease();

}

HRESULT FAR EXPORT CTestOCXCtrl::XObjSafe::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)

{

    METHOD_PROLOGUE(CTestOCXCtrl, ObjSafe)

    return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);

}

const DWORD dwSupportedBits = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;

const DWORD dwNotSupportedBits = ~ dwSupportedBits;

//.............................................................................

// CStopLiteCtrl::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 

CTestOCXCtrl::XObjSafe::GetInterfaceSafetyOptions( 

 /* [in] */ REFIID riid,

 /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,

 /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)

{

    METHOD_PROLOGUE(CTestOCXCtrl, 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

}

/
// CStopLiteCtrl::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 
CTestOCXCtrl::XObjSafe::SetInterfaceSafetyOptions(

 /* [in] */ REFIID riid,

 /* [in] */ DWORD dwOptionSetMask,

 /* [in] */ DWORD dwEnabledOptions)

{

    METHOD_PROLOGUE(CTestOCXCtrl, 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);
}

//***************************************************************add end

完成上述步骤之后,编译,在HTML中添加

<!-- saved from url=(0017)http://localhost/ -->

应该就不会弹出安全警告了。

当然此警告也可通过手动修改IE-安全设置 暂时屏蔽,但不建议。

6.查看ocx或dll文件依赖项列表的方法

使用vs2010命令提示工具,输入命令: dumpbin /dependents [文件完整路径]

01 , 01.txt 《 VB6.0中通过MSChart控件调用数据库 》 02 , 02.txt 《 用VB6实现动态增减控件 》 03 , 03.txt ActiveX控件的创建 04 , 04.txt ADO控件和DATA控件的冲突(不能共存)的解决方法 05 , 05.txt Combo的自动查询技术 06 , 06.txt DirectX7.0使用心得(1) 07 , 07.txt DirectX7.0使用心得(2) 08 , 08.txt DirectX7.0使用心得(3) 09 , 09.txt FSO对象模型在VB中的应用 10 , 10.txt MsComm 控件的文字传输范例 11 , 11.txt Office或IE4风格的ToolBar 12 , 12.txt Regsvr32.exe注册控件的具体用法 13 , 13.txt TextBox的自动调节 14 , 14.txt TextBox实现打印机效果 15 , 15.txt TreeView的基本操作 16 , 16.txt VB5中DBGRID控件在VB6中使用 17 , 17.txt VB6.0动态加载ActiveX控件漫谈 18 , 18.txt VB与MS-Draw开发通用作图软件 19 , 19.txt VB中APP对象及其应用 20 , 20.txt VB中list控件的功能扩充 21 , 21.txt VB中防止将重复项目添加到列表框控件中 22 , 22.txt VB中用Multimedia MCI控件开发多媒体应用 23 , 23.txt Win Api在VB中的妙用 24 , 24.txt WINDOWS SCRIPT HOST对象在VB中的使用 25 , 25.txt 安装向导生成程序组并建立多个程序项 26 , 26.txt 保存复选框选项 27 , 27.txt 不用OCX来创建自己的控件(一) 28 , 28.txt 成组更新控件属性 29 , 29.txt 创建数据驱动窗体 30 , 30.txt 得到鼠标位置 31 , 31.txt 调整 Combo 下拉部分的宽度 32 , 32.txt 动态加入控件到VB控件数组中 33 , 33.txt 对ListView中的列排序 34 , 34.txt 放一个Combo到Toolbar中 35 , 35.txt 改变 ListIndex而不发生 Click 事
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值