转自:http://hi.baidu.com/tiancaiyan8/blog/item/06441b355635891991ef397c.html

用MFC ActiveX Control Wizard生成的OCX控件,Web直接调用失败,因为IE在调用之前会先检测控件有没有安全机制。详见:http://msdn2.microsoft.com/en-us/library/Aa751977.aspx#Mtps_DropDownFilterText

解决方案有2种:

1、OCX注册同时注册安全入口

2、实现安全接口IObjectSafety

具体实现:

第一种:OCX注册同时注册安全入口

修改XXX.cpp文件(OCXTest-XXX):

// OCXTest.cpp : COCXTestApp 和 DLL 注册的实现。

#include "stdafx.h" 
#include "OCXTest.h"

#include <objsafe.h>

#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif

COCXTestApp NEAR theApp;

const GUID CDECL BASED_CODE _tlid = 
   { 0xE62AE89, 0x4574, 0x470D, { 0x91, 0x25, 0x5D, 0xD3, 0xFB, 0xE6, 0x9D, 0x12 } };

const WORD _wVerMajor = 1; 
const WORD _wVerMinor = 0;

// 与该控件的guid一致

const GUID CDECL CLSID_SafeItem = 
    { 0x10b49e1a, 0x28d8, 0x44f2, { 0xb2, 0x53, 0xb, 0x31, 0x54, 0x79, 0x67, 0x54} };

// COCXTestApp::InitInstance - DLL 初始化

BOOL COCXTestApp::InitInstance() 

BOOL bInit = COleControlModule::InitInstance();

return bInit; 
}

// COCXTestApp::ExitInstance - DLL 终止

int COCXTestApp::ExitInstance() 

// TODO: 在此添加您自己的模块终止代码。

return COleControlModule::ExitInstance(); 
}

// 创建组件种类 
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

// Make sure the provided description is not too long. 
    // Only copy the first 127 characters if it is. 
    int len = wcslen(catDescription); 
    if (len>127) 
        len = 127; 
    wcsncpy(catinfo.szDescription, catDescription, len); 
    // Make sure the description is null terminated. 
    catinfo.szDescription[len] = '/0';

hr = pcr->RegisterCategories(1, &catinfo); 
        pcr->Release();

return hr; 
}

// 注册组件种类 
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(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; 
}

// DllRegisterServer - 将项添加到系统注册表

STDAPI DllRegisterServer(void) 

AFX_MANAGE_STATE(_afxModuleAddrThis);

if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid)) 
   return ResultFromScode(SELFREG_E_TYPELIB);

if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE)) 
   return ResultFromScode(SELFREG_E_CLASS);

HRESULT hr = S_OK; 
// 标记控件初始化安全. 
    // 创建初始化安全组件种类 
    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;

// 标记控件脚本安全 
    // 创建脚本安全组件种类 
    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 - 将项从系统注册表中移除

STDAPI DllUnregisterServer(void) 

AFX_MANAGE_STATE(_afxModuleAddrThis);

HRESULT hr = S_OK; 
// 删除控件初始化安全入口. 
    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; 
}

第2种:实现安全接口IObjectSafety

需要头文件:#include "objsafe.h"

1、在XXXCtrl.h文件中DECLARE_DYNCREATE(CXXXCtrl)后添加:

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);

2、在XXXCtrl.cpp文件中UpdateRegistry函数之后添加:


// Interface map for IObjectSafety

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;


// 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 
COCXTestCtrl::XObjSafe::GetInterfaceSafetyOptions( 
/* [in] */ REFIID riid, 
        /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions, 
        /* [out] */ 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 
}


// 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 
COCXTestCtrl::XObjSafe::SetInterfaceSafetyOptions( 
        /* [in] */ REFIID riid, 
        /* [in] */ DWORD dwOptionSetMask, 
        /* [in] */ 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); 
}

3、IE如何响应ActiveX控件事件

第一种:手动实现连接点 
    这几天在开发过程中遇到一个问题,即在网页中无法响应ActiveX控件自定义事件。经查资料后,明白ActiveX控件的事件如果要 
通过#等脚本语言响应,必须实现IProvideClassInfo或者IProvideClassInfo2接口。因为脚本语言必须通过这个接口获 
得控件的接口信息。

用MFC ActiveX Control Wizard生成的项目,其接口的实现是通过嵌套类完成,要实现IProvideClassInfo接口我们可以按下列步骤进行: 
1. 在COleControl的继承类.h文件中DECLARE_DYNCREATE(CXXXCtrl)后加入代码: 
DECLARE_INTERFACE_MAP() 
        BEGIN_INTERFACE_PART(ProvideClassInfo, IProvideClassInfo) 
            STDMETHOD_(HRESULT, GetClassInfo) ( 
                  /*[out] */ITypeInfo** ppTI 
            ); 
        END_INTERFACE_PART(ProvideClassInfo);

2. 在COleControl的继承类.cpp文件中UpdateRegistry函数后加入代码,并实现接口: 
        BEGIN_INTERFACE_MAP( CMetaKM_FC_BCtrl, COleControl ) 
             INTERFACE_PART(CMetaKM_FC_BCtrl, IID_IProvideClassInfo, ProvideClassInfo) 
        END_INTERFACE_MAP()

ULONG FAR EXPORT CMetaKM_FC_BCtrl::XProvideClassInfo::AddRef() 

    METHOD_PROLOGUE(CMetaKM_FC_BCtrl, ProvideClassInfo) 
return pThis->ExternalAddRef(); 
}

ULONG FAR EXPORT CMetaKM_FC_BCtrl::XProvideClassInfo::Release() 

     METHOD_PROLOGUE(CMetaKM_FC_BCtrl, ProvideClassInfo) 
   return pThis->ExternalRelease(); 
}

HRESULT STDMETHODCALLTYPE 
CMetaKM_FC_BCtrl::XProvideClassInfo::QueryInterface ( 
REFIID iid, void FAR* FAR* ppvObj) 

METHOD_PROLOGUE(CMetaKM_FC_BCtrl, ProvideClassInfo) 
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj); 
}

HRESULT STDMETHODCALLTYPE 
CMetaKM_FC_BCtrl::XProvideClassInfo::GetClassInfo ( 
               /* [out] */ITypeInfo** ppTypeInfo 
               ) 

METHOD_PROLOGUE(CMetaKM_FC_BCtrl, ProvideClassInfo)

HRESULT hr; 
CLSID clsid; 
   pThis->GetClassID(&clsid);

hr = pThis->GetTypeInfoOfGuid(GetUserDefaultLCID(), clsid, ppTypeInfo);

return hr; 
}

如果是用ATL COM Wizard生成的工程,那么在New ATL Object时可以选择Full Control,该选项默认已经实现IProvideClassInfo2接口 
。如果选择其他轻量级ActiveX对象,那么实现IProvideClassInfo2接口也相当容易。因为ATL COM Wizard生成的工程,对于接口的实现 
时通过多重继承完成的,只有在接口定义中加入继承IProvideClassInfo2即可。 
1. 在接口定义中加入: 
    public IProvideClassInfo2Impl<&CLSID_MetaKM_FC_B, &DIID__IMetaKM_FC_BEvents, &LIBID_METAKM_FC_CTRLLib> 
2.在BEGIN_COM_MAP(CMetaKM_FC_B)与END_COM_MAP()对中加入COM_INTERFACE_ENTRY(IProvideClassInfo)和COM_INTERFACE_ENTRY(IProvideClassInfo2)

第二种:通过ActiveX属性通知IE

步骤:

在ActiveX中添加一个属性:Idispatch* EventNotify;

对应变量为Idispatch* m_EventNotify;

属性函数:

Idispatch* C***Ctrl::GetEventNotify(void)

{

return EventNotify;

}

void SetEventNotify(Idispatch* pVal)

{

m_EventNotify = pVal;

}

自定义函数作为事件通知函数:

void OnEventNotify()

{

if(m_EventNotify==NULL) return ;

DISPPARAMS dispparamNoArgs = {NULL,NULL,0,0};

HRESULT hr = m_EventNotify->Invoke(0, IID_NULL, LOCAL_USER_DEFAULT, DISPATCH_METHOD,

&dispparamNoArgs ,NULL,NULL,NULL);

}

现在ActiveX的事件做好了,只要在调用 OnEventNotify()就能激发。在Web中只要用#将事件函数名赋给控件的属性EventNotify就能连通了。

例如:

<OBJECT id="obj" type="application/x-oleobject"

height="400" width="500" classid="CLSID:控件的guid" VIEWASTEXT>

</OBJECT>

<a id=process href="#:testevent()">test</a>

<script>

obj.EventNotify=eventfunc;

function eventfunc(){

// alert(111);   }

function testevent(){

obj.DriveEvent();

}

</script>

ocx注册成功但是页面不显示相关推荐

  1. 需求:有一个首页,首页中有登录和注册 1. 点击注册进入注册页面。成功注册后,在页面中显示 “恭喜您,注册成功,页面内将在5秒后跳转到个人主页,点击这里立即跳转” 。进入个人主页后显示当前的时间。

    1.项目所需的jar包 导包:c3p0包.dbut ils包.servlet包,c3p0依赖包以及c3p0文件配置. 创建一个数据库day0914,并创建一个表user用于数据的存储. 数据库相关的包 ...

  2. java web用jsp编写注册页面提交后显示注册成功页面

    一.相关功能和步骤 1.编写jsp注册页面(zc.jsp),用户从表格中输入,使用合适的jsp内置对象来处理注册页面访问的次数(每访问一次注册页面次数+1),界面如下: 2.当注册信息填写完后,点击提 ...

  3. 项目启动成功,但是Eureka页面不显示

    今天开始学习Eureka,但是按照网上配置好环境之后,发现了下面两个问题,特别记录下来. Eureka的home页面不显示 界面正常显示,但是显示没有注册的服务 别的项目怎么进行注册 一.Eureka ...

  4. 【web结课大作业】创建一个注册页面并引用正则表达式,点击注册按钮后可以弹窗显示刚刚注册输入的信息(表单传值)

    这个代码有借鉴其它博主的部分,借鉴了别的博主的css样式和框架(嘻嘻算是站在巨人的肩膀上),内容自己改了七七八八.参考博文如下(这个原博文只能实现正则判断,没有表单传值功能): HTML--登录.注册 ...

  5. layui table数据表格中数据返回成功,但页面不显示数据内容问题

    layui table数据表格中数据返回成功,但页面不显示数据内容问题. 这是我做毕业设计的时候自己遇到的问题,后来查看了网上的一些技术贴子而得到解决,所以便想总结一个大概的方法,供大家参考! 一般导 ...

  6. 关于注册成功,进入提示页面,然后跳转

    最近在做注册功能的时候,需要在注册成功之后进入提示页面,然后在做其他跳转 基本的流程是: 1.register.jsp页面注册,页面校验过后进入springmvc controller,insert成 ...

  7. XXL-JOB执行器注册成功但是在管理界面里不显示

    场景描述: 在配置正确,调度中心admin和执行器executor启动成功的情况下,在管理界面看不到我们的执行器,只能看到xxl的示例执行器. 但是在xxl_job_registry表里(执行器注册成 ...

  8. 【3】用户注册账户,如果注册的名字存在,提示已经存在,不能使用该名字注册,如果没有,则显示注册成功

    /** 注册一个名字,如果存在就提示:用户被注册,* */ public class RegisterName {//定义一个数组,存放已经注册了的用户名static String[] name={& ...

  9. java错误页面显示错误信息_Struts2在JSP页面中显示错误信息和提示信息的方法

    Struts2在JSP页面中显示错误信息和提示信息的方法主要有以下四种. 注意:以下四种方法均需要使Action类继承ActionSupport类. 一.域级错误信息 ①重写Action中的valid ...

  10. 一个html页面上显示dopost,Java遇见HTML-servlet(一)

    Java遇见HTML的6篇文章技术较老只是在熟悉java基础知识和了解mvc模型思想 servlet的应用 servlet可以理解为就是一个jsp,实现servlet有三步: 1.在web.xml中注 ...

最新文章

  1. R语言使用ggplot2包的快速可视化函数qplot绘制散点图实战
  2. c语言中 char怎样用,C语言中char*和char[]用法区别分析
  3. Xamarin.Forms单元控件Cell
  4. 解决Visual SVN在linux下不能访问的问题
  5. 乐观锁和悲观锁的使用场景及应用——Java高并发系列学习笔记
  6. Perl语言入门-第四章-子程序-习题
  7. JVM教程:JM内存分哪几个区,每个区的作用是什么?
  8. Atitit. 获取cpu占有率的 java c# .net php node.js的实现
  9. matlab 正交park变换 功率守恒,克拉克(CLARKE)和帕克(PARK)变换.doc
  10. C++ emplace_back
  11. Android 常见界面控件(简单控件篇)
  12. 计算机管理 存储空间不足,Win7系统提示“存储空间不足,无法处理此命令”怎么办?...
  13. 不输给MacBook的win10精确式触摸板
  14. APM的3DR无线数传的安装和调试
  15. 捕鱼游戏源码(数值+完整项目资源)
  16. 非线性微分方程的平均法
  17. C#之判断字母大小、字母转ACII码
  18. 空间相机的像质评价体系
  19. hihocoder #1163 : 博弈游戏·Nim游戏
  20. 财务报表分析:理论框架方法与案例

热门文章

  1. Java IO多路复用机制详解
  2. linux添加终端快捷键,linux 终端快捷键
  3. 生产排程系统_ASPROVA:工序排程软件的全球隐形冠军
  4. 硬盘保修查询网站明细清单希捷硬盘保修查询西数硬盘保修查
  5. 在RStudio里面部署Python
  6. 解决窗口桌面管理器内存占用过高,系统更新,核显驱动异常造成的内存泄漏问题。
  7. 微信小程序开发入门介绍-布局组件
  8. React脚手架使用less
  9. 微信公众号唤起微信支付
  10. java int转byte数组