直接开始VS2008 ActiveX开发教程
开发环境准备

- 必备软件: 安装 Visual Studio 2008 (推荐 Professional 或更高版本),确保安装时选择了 Visual C++ 和 MFC 组件。
- 目标平台识别: 明确你的 ActiveX 控件将在什么环境下运行 (如:特定浏览器 IE、旧版业务系统 XP/Win7),这决定了项目设置中的运行时库 (如
/MT或/MD) 和代码安全要求。 - 项目创建启动: 打开 VS2008 ->
文件->新建->项目,在Visual C++->MFC下选择 “MFC ActiveX 控件”,输入项目名 (如MyFirstCtrl),选择位置,点击确定,在向导中:- 控件设置: 保持默认命名或修改 (影响后续的 CLSID、ProgID)。
- 功能选择: 勾选
在“插入对象”对话框中可用、运行时不可见(按需)、关于框(可选),其他高级特性如复合控件、异步加载按需勾选。 - 控件子类化 (可选): 若需基于标准 Windows 控件 (如按钮、列表框) 构建,在此处选择,否则创建空白控件。
- 完成向导: 点击
完成,VS 自动生成框架代码和基础文件 (.cpp, .h, .idl, .rgs, .def)。
理解生成的核心文件
- MyFirstCtrlCtrl.h/.cpp: 控件主类 (
CMyFirstCtrlCtrl) 的实现,继承自COleControl,核心逻辑所在。 - MyFirstCtrl.idl: 接口定义语言文件,定义控件暴露的属性、方法和事件接口,后续添加接口在此修改。
- MyFirstCtrl.rgs: 注册表脚本,控件注册/注销时写入/删除的注册表项,包含 CLSID、ProgID、线程模型等关键信息。
- MyFirstCtrl.def: 模块定义文件,导出 DLL 函数 (如
DllRegisterServer,DllGetClassObject)。
实现核心功能:属性与方法
- 添加自定义属性 (Property):
- 在
类视图中右键控件类 (CMyFirstCtrlCtrl) ->添加->添加属性。 - 输入属性名 (如
TextColor),选择类型 (如OLE_COLOR),通常选择成员变量方式实现。 - VS 会自动在
.h文件中添加成员变量 (如m_textColor) 和在.cpp中添加Get/Set函数骨架及调度映射 (DISP_PROPERTY),在GetTextColor()和SetTextColor()中实现具体逻辑。
- 在
- 添加自定义方法 (Method):
- 在
类视图中右键控件类 ->添加->添加方法。 - 输入方法名 (如
ShowMessage),设置返回类型 (如void) 和参数 (如[in] BSTR bstrMsg)。 - VS 生成方法声明和调度映射 (
DISP_FUNCTION),在方法实现 (ShowMessage) 中编写功能代码 (如:MessageBoxW(NULL, bstrMsg, L"ActiveX Message", MB_OK);)。
- 在
- 修改 .idl 文件: 添加属性/方法后,检查
.idl文件,确保dispinterface或coclass部分已正确包含新添加的接口描述,编译时会自动调用 MIDL 编译此文件生成类型库 (.tlb)。
实现事件 (Events)
ActiveX 控件通过连接点 (Connection Point) 向容器 (如网页) 触发事件。
- 添加事件: 在
类视图中右键控件类 ->添加->添加事件。 - 定义事件: 输入事件名 (如
OnTextChanged),设置参数 (如[in] BSTR bstrNewText)。 - 代码生成: VS 自动:
- 在
.h文件中声明事件触发函数FireOnTextChanged(BSTR bstrNewText)。 - 在
.cpp中实现该函数 (内部调用FireEvent),并添加到事件映射 (EVENT_CUSTOM或EVENT_CUSTOM_ID)。 - 更新
.idl文件的_DMyFirstCtrlEventsdispinterface。
- 在
- 触发事件: 在控件逻辑需要的地方 (如属性
Text的Set方法内部),调用FireOnTextChanged(m_bstrText);。
设计用户界面 (UI)

- 资源编辑: 打开
资源视图->Dialog,找到控件的对话框资源 (通常为IDD_MYFIRSTCTRL),使用工具箱拖放标准 Windows 控件 (按钮、编辑框等)。 - 关联控件变量: 右键对话框上的控件 ->
添加变量,选择控件变量,并关联到控件类中的成员变量 (如CEdit m_edtDisplay;)。 - 重写绘制: 如需自绘,重写
OnDraw(CDC pdc, const CRect& rcBounds, const CRect& rcInvalid),使用pdc进行 GDI 绘图操作,注意坐标在rcBounds内。
持久化 (Persistence)
控件状态 (属性值) 需在容器保存/加载时持久化。
- 实现
DoPropExchange: 在控件类中重写此函数,使用PX_系列函数序列化属性:void CMyFirstCtrlCtrl::DoPropExchange(CPropExchange pPX) { ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor)); COleControl::DoPropExchange(pPX); PX_Long(pPX, _T("BackColor"), m_backColor, RGB(0xFF, 0xFF, 0xFF)); // 示例 PX_String(pPX, _T("Caption"), m_caption, _T("Default Caption")); // 示例 }
安全性与 IObjectSafety
现代浏览器 (尤其是保护模式下的 IE) 对 ActiveX 有严格安全要求,实现 IObjectSafety 接口告知容器控件是安全的。
- 添加接口: 在
类视图中右键控件类 ->添加->添加接口,选择IObjectSafety。 - 实现方法: 在生成的
IObjectSafety实现类中 (如CMyFirstCtrlCtrl::XObjectSafety),实现GetInterfaceSafetyOptions和SetInterfaceSafetyOptions,通常返回控件支持的安全选项 (如INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA) 并处理设置请求。 - 更新注册表 (.rgs): 在控件的注册项下添加
Implemented Categories键及其子键,注册控件实现的组件类别 (CATID):NoRemove Implemented Categories { {7DD95801-9882-11CF-9FA9-00AA006C42C4} // CATID_SafeForScripting {7DD95802-9882-11CF-9FA9-00AA006C42C4} // CATID_SafeForInitializing }
编译、注册与调试
- 编译: 选择
Release配置 (确保/O2优化开启),按F7编译生成.ocx文件。 - 注册:
- 开发机: 以管理员身份运行 VS2008。
生成->注册 MyFirstCtrl.ocx(或手动执行regsvr32.exe pathtoMyFirstCtrl.ocx)。 - 部署: 创建安装包 (如使用 InstallShield Limited Edition for VS2008) 处理注册。
- 开发机: 以管理员身份运行 VS2008。
- 调试:
- 设置项目属性:
调试->命令填入容器路径 (如C:Program FilesInternet Exploreriexplore.exe)。 命令参数填入包含控件的测试 HTML 文件路径 (如"C:Testtest.html")。- 在控件代码中设置断点,按
F5启动调试,IE 将启动并加载测试页,命中断点后即可调试。
- 设置项目属性:
在网页中使用 (HTML/JS)
创建测试 HTML 文件:

<!DOCTYPE html>
<html>
<head>MyFirstCtrl Test</title>
<script>
function InitializeControl() {
var ctrl = document.getElementById("MyCtrl");
ctrl.TextColor = 0xFF0000; // 红色 (OLE_COLOR)
ctrl.Caption = "Hello ActiveX!";
}
function CallShowMessage() {
var ctrl = document.getElementById("MyCtrl");
ctrl.ShowMessage("This is from JavaScript!");
}
</script>
</head>
<body onload="InitializeControl()">
<object id="MyCtrl" classid="clsid:YOUR-CONTROL-CLSID-HERE" width="300" height="200">
<param name="BackColor" value="16777215"> <!-- 白色 -->
</object>
<br>
<button onclick="CallShowMessage()">Show Message</button>
</body>
</html>
- 将
YOUR-CONTROL-CLSID-HERE替换为控件实际的 CLSID (在.idl文件或生成的i.h文件中查找)。 <param>标签用于设置设计时属性。
关键注意事项与高级技巧
- 线程模型: 默认项目生成的注册表脚本 (
rgs) 通常指定Apartment(STA),确保控件代码线程安全,或根据实际使用环境调整 (如标记为Free或Both),错误模型会导致崩溃。 - 浏览器兼容性: ActiveX 主要限于旧版 IE (Trident),明确告知用户运行环境要求,对于新 Edge (Chromium),ActiveX 默认不支持。
- 内存管理: 严格遵守 COM 内存规则,使用
BSTR时注意SysAllocString/SysFreeString;传递接口指针时正确使用AddRef/Release,智能指针 (CComBSTR,CComPtr,CComQIPtr) 是防止泄漏的利器。 - 错误处理: 在方法和属性访问器中,使用
COleControl::ThrowError或设置SetNotSupported/SetNotPermitted向容器返回丰富的错误信息 (HRESULT, 描述)。 - 许可证 (Licensing): 如需分发限制,实现许可支持 (
IClassFactory2),VS向导可添加基础支持。 - 性能优化: 避免在频繁调用的方法 (如
OnDraw) 中进行耗时操作,缓存 GDI 对象,考虑异步操作。 - 数字签名: 强烈建议 对最终发布的
.ocx进行 Authenticode 代码签名,否则用户会遇到严重安全警告甚至阻止运行,获取商业代码签名证书是关键部署步骤。
安全实践:超越基础
- 输入验证: 对所有从容器 (JS) 传入的参数进行严格验证 (类型、范围、长度),防止缓冲区溢出或注入攻击。
- 最小特权: 控件不应要求管理员权限执行常规功能,避免操作注册表敏感区域或系统文件,除非绝对必要且有明确用户授权。
- 沙箱考虑: 理解 IE 保护模式 (低完整性级别),控件如需访问用户文件,应通过安全文件对话框 (
IFileDialog) 或处理PersistStreamInit让容器处理持久化。 - 废弃 API 规避: 避免使用已知不安全的旧 API (如
strcpy,sprintf),改用安全版本 (strcpy_s,sprintf_s) 或 ATL/MFC 包装类 (CString)。
互动:您在实际项目中遇到过哪些ActiveX开发的独特挑战?或者对于将遗留ActiveX功能迁移到现代Web技术有什么具体想法?欢迎分享您的经验或提问!
原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/17725.html