在 C++Builder (BCB) 開發 ActiveX 控制項 (OCX) 並嵌入網頁時,Internet Explorer 預設會阻擋未標記為「安全給指令碼」與「安全初始化」的控制項,導致腳本無法存取控制項屬性/方法,或控制項無法載入。本文說明如何在 ATL 專案中透過 元件類別對應 (Category Map) 宣告這兩項安全類別,使控制項通過 IE 安全性檢查。
在控制項實作類別 (通常命名為 TxxxImpl) 內部,於 BEGIN_COM_MAP 之後、BEGIN_PROPERTY_MAP 之前加入以下巨集區塊:
// 安全類別宣告區塊
BEGIN_CATEGORY_MAP(TYourControlImpl)
IMPLEMENTED_CATEGORY(CATID_SafeForScripting) // 安全給指令碼
IMPLEMENTED_CATEGORY(CATID_SafeForInitializing) // 安全初始化
END_CATEGORY_MAP()
class ATL_NO_VTABLE TSignActiveFormXImpl :
public VCLCONTROL_IMPL(TSignActiveFormXImpl, SignActiveFormX, TSignActiveFormX, ISignActiveFormX, DIID_ISignActiveFormXEvents)
{
// ... 事件處理函數宣告 ...
void __fastcall ActivateEvent(TObject *Sender);
// ... 其他事件 ...
public:
void InitializeControl()
{
m_VclCtl->OnActivate = ActivateEvent;
m_VclCtl->OnClick = ClickEvent;
// ... 綁定其他事件 ...
}
// COM 介面對應表
BEGIN_COM_MAP(TSignActiveFormXImpl)
VCL_CONTROL_COM_INTERFACE_ENTRIES(ISignActiveFormX)
END_COM_MAP()
// ★ 關鍵:安全類別宣告 ★
BEGIN_CATEGORY_MAP(TSignActiveFormXImpl)
IMPLEMENTED_CATEGORY(CATID_SafeForScripting)
IMPLEMENTED_CATEGORY(CATID_SafeForInitializing)
END_CATEGORY_MAP()
// 屬性對應表
BEGIN_PROPERTY_MAP(TSignActiveFormXImpl)
// PROP_PAGE(CLSID_SignActiveFormXPage)
END_PROPERTY_MAP()
// VCL 控制項持久化宣告
DECLARE_VCL_CONTROL_PERSISTENCE(TSignActiveFormXImpl, TSignActiveFormX);
// ActiveX 控制項註冊資訊
DECLARE_ACTIVEXCONTROL_REGISTRY("SignActiveFormProj1.SignActiveFormX", 1);
protected:
// ... 介面方法宣告 (STDMETHOD) ...
STDMETHOD(get_SignStr(BSTR* Value));
STDMETHOD(set_SignStr(BSTR Value));
STDMETHOD(test(BSTR str));
// ... 其他方法 ...
};
IPersistPropertyBag::InitNew 或 IPersistStreamInit::InitNew 安全初始化,不會因惡意參數導致系統損害。<olectl.h>,對應 GUID 分別為:
{7DD95801-9882-11CF-9FA9-00AA006C42C4}{7DD95802-9882-11CF-9FA9-00AA006C42C4}regsvr32),ATL 會自動在登錄表 HKCR\CLSID\{YourCLSID}\Implemented Categories 下建立這兩個類別的子鍵,IE 掃描到即視為安全。.ocx。regsvr32 YourControl.ocx 註冊。regedit,檢查 HKEY_CLASSES_ROOT\CLSID\{YourControlCLSID}\Implemented Categories 下是否存在上述兩個 GUID 子鍵。<object classid="clsid:YourCLSID"></object> 嵌入控制項,並嘗試用 JavaScript 呼叫方法/存取屬性。| 問題 | 原因與解決 |
|---|---|
| 仍被 IE 阻擋 | 確認專案設定 「啟用 ActiveX 控制項安全性」;清除 IE 快取;檢查登錄表類別是否正確寫入。 |
| 簽署控制項 | 企業環境建議使用 signcode 或 SignTool 為 .ocx 加上數位簽章,並透過群組原則信任發行者,徹底解決安全提示。 |
| VCL 控制項特有 | BCB 產生的 ActiveForm 專案預設不含 Category Map,需手動加入。若專案遷移至 BCB 4.0 以上,注意 DECLARE_VCL_CONTROL_PERSISTENCE 巨集相容性。 |
在 C++Builder ATL ActiveX 專案中,只需在控制項實作類別加入 BEGIN_CATEGORY_MAP 區塊並宣告 CATID_SafeForScripting、CATID_SafeForInitializing 兩個巨集,重新編譯註冊即可讓控制項在 IE 中正常被腳本存取與初始化。這是發布網頁嵌入式 ActiveX 控制項的必要步驟。