开发基于网页的ActiveX控制

开发基于网页的ActiveX控制

以前工作的时候写过一个ActiveX控件,一直想将其用在网页上,但始终没有成功,今天无意中在MSDN上看到了《Using ActiveX Controls to Automate Your Web Pages》-http://msdn.microsoft.com/library/default.asp?url=/workshop/components/activex/tutorial.asp,似乎与之相关。此文中设计了一个基于Timer的时钟ActiveX控件并将其嵌入到web页面上。当然,本文的重点是在强调基于web页面的ActiveX控件的安全性问题。要使得安全的ActiveX控件在web页面上也安全的话,必须确保调用它的页面脚本(Script)也是安全的,即safe for initialization and/or scripting。要做到这后一点,有两种方法:

  1. 用Component Categories Manager 在系统的注册表中添加适当的entry,这样IE在加载ActiveX控件前就会先检查注册表上的Entry;
  2. 在控件中实现IObjectSafety接口,如果IE检测到ActiveX控件支持IObjectSafety接口,就会调用IObjectSafety::SetInterfaceSafetyOptions方法以判定该控件是否安全;

在第一种方法中,Component Categories Manager会在注册表中为每个组件包含一个Component Categories key ,并且每个key都有两个subkey,一个是CATID_SafeForScripting ,另一个是CATID_SafeForInitializing。创建subkey的方法是:

  1. Create an instance of the Component Categories Manager and retrieve the address of the ICatRegister interface.
  2. Set the appropriate members of a CATEGORYINFO structure.
  3. Call the ICatRegister::RegisterCategories method, passing the address of the initialized CATEGORYINFO structure.

将以下步骤写成一个函数CreateComponentCategory 如下:

#include "comcat.h"
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;
}
在创建了subkey以后,控件必须注册成为该类别(category),要做到这一点,必须:
  1. Create an instance of the Component Categories Manager and retrieve the address of  the ICatRegister interface.
  2. Call the ICatRegister::RegisterClassImplCategories method, passing the control's class identifier (CLSID) and the requisite category ID as arguments.

以上步骤写成以下函数(RegisterCLSIDInCategory ):

#include "comcat.h"
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;

}

DllRegisterServer函数被调用时,控件应该调用以上两个函数,以实现safe for initilization
以及safe for scripting,示例如下:
STDAPI DllRegisterServer(void)
{
    HRESULT  hr;    // return for 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;
}
同上一样,也必须对类别进行unregister,相应的函数为:
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;
}
在对应的DllUnRegisterServer中,也应该调用上面函数:
STDAPI DllUnregisterServer(void)
{
    HRESULT hr;    // HResult used by Safety Functions

    AFX_MANAGE_STATE(_afxModuleAddrThis);

    if (!AfxOleUnregisterTypeLib(_tlid)) 
        return ResultFromScode(SELFREG_E_TYPELIB);

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

    // Remove entries from the registry.

    hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if (FAILED(hr))
        return hr;

    hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if (FAILED(hr))
        return hr;

    return NOERROR;
}
以上调用可以改为以下:
BOOL CONotesCtlCtrl::CONotesCtlCtrlFactory::UpdateRegistry(BOOL bRegister)
{
 // TODO: Verify that your control follows apartment-model threading rules.
 // Refer to MFC TechNote 64 for more information.
 // If your control does not conform to the apartment-model rules, then
 // you must modify the code below, changing the 6th parameter from
 // afxRegInsertable | afxRegApartmentThreading to afxRegInsertable.
 HRESULT hr;
 if (bRegister)
 {
        if(!AfxOleRegisterControlClass(
  AfxGetInstanceHandle(),
  m_clsid,
  m_lpszProgID,
  IDS_ONOTESCTL,
  IDB_ONOTESCTL,
  afxRegInsertable | afxRegApartmentThreading,
  _dwONotesCtlOleMisc,
  _tlid,
  _wVerMajor,
  _wVerMinor)) return FALSE;
   hr = CreateComponentCategory(CATID_SafeForScripting,L"Controls that are safely scriptable") ;
   hr = CreateComponentCategory (CATID_SafeForInitializing,L"Controls safely initializable from persistent data");
   
   hr = RegisterCLSIDInCategory (m_clsid, CATID_SafeForScripting) ;
   hr = RegisterCLSIDInCategory (m_clsid,CATID_SafeForInitializing);
   return TRUE;
 }
 else
 {
  if(!AfxOleUnregisterClass(m_clsid, m_lpszProgID))
   return FALSE;
  hr = UnRegisterCLSIDInCategory (m_clsid,CATID_SafeForScripting);
  hr = UnRegisterCLSIDInCategory (m_clsid,CATID_SafeForInitializing) ;
  return TRUE;
 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值