{vs2010开发ocx} 使用 Visual Studio 2010 开发 OCX (ActiveX) 控件是一项经典且强大的技术,用于创建可嵌入网页、VB6、Delphi 甚至 .NET WinForms 应用程序的可重用组件,虽然现代开发更多转向 .NET 控件或 Web 组件,但在特定遗留系统集成或需要底层性能控制的场景下,OCX 仍有其价值,本教程将详细指导你完成在 VS2010 中创建、实现、调试和部署一个基础但功能完整的 OCX 控件。

环境准备与项目创建
-
安装必备项:
- 确保已安装 Visual Studio 2010 (Professional 或 Ultimate 版)。
- 安装时勾选 Visual C++ 开发组件,特别是 ATL (Active Template Library),ATL 是高效开发 COM/ActiveX 组件的基石。
-
创建 ATL 项目:
- 启动 VS2010,选择
File -> New -> Project...。 - 在
Installed Templates下,展开Visual C++,选择ATL。 - 选择
ATL Project模板。 - 为项目命名 (
MyFirstOCX) 并选择保存位置,点击OK。 - 在
ATL Project Wizard中:Application Settings选项卡:保留默认设置 (Dynamic-link library (DLL))。关键点: 确保Attributed选项取消勾选,VS2010 的属性化 ATL 支持不如经典 ATL 稳定和广泛兼容,对于 OCX 开发推荐经典方式。- 其他选项卡通常保持默认即可,点击
Finish。
- 启动 VS2010,选择
添加 ATL 控件类
项目创建后,你需要添加具体的控件类:
-
添加简单对象:
- 在
Solution Explorer中,右键点击项目名称 (MyFirstOCX),选择Add -> Class...。 - 在
Add Class对话框中,选择ATL类别下的ATL Control,点击Add。
- 在
-
配置控件向导:
Names选项卡:Short name: 输入控件核心名称 (SimpleButton)。- 其他字段 (
Class,.h file,.cpp file,CoClass,Interface) 会自动生成,通常无需修改,注意Interface名称 (如ISimpleButton) 是控件的核心编程接口。
Options选项卡:这是关键配置页!Control type: 选择Standard Control。- 勾选
Support Connection Points: 这是控件能够触发事件 (如 Click) 的基础。 - 勾选
Support IObjectSafety: 强烈建议勾选! 该接口帮助标记控件对脚本和初始化是否安全,是提高 Web 嵌入安全性和通过浏览器安全警告的关键。 Aggregation: 通常选择Only(允许聚合) 或No(不允许聚合),根据需求定。Only更通用。Interface: 选择Dual,这允许控件同时通过早期绑定 (vtable) 和后期绑定 (IDispatch) 被调用,兼容性最好。Support ISupportErrorInfo: 可选,用于更丰富的错误信息。Support View Status: 可选,用于在容器中控制控件外观状态。- 其他选项如
Free Threaded Marshaler通常保持默认 (不勾选) 即可。
Appearance选项卡:设置控件初始外观(宽度、高度)、是否添加About Box方法等。Stock Properties选项卡:可以勾选需要支持的常用库存属性,如BackColor,ForeColor,Caption,Font,Enabled,BorderStyle等,选择这些会自动为控件添加对这些标准属性的支持。- 点击
Finish。
设计控件界面与添加成员变量
向导完成后,VS2010 会生成控件的骨架代码,包括类定义 (CSimpleButton)、接口定义 (ISimpleButton)、连接点接口 (_ISimpleButtonEvents) 和资源 (对话框模板用于 About 框)。
-
编辑控件资源视图:

- 在
Resource View(可通过View -> Other Windows -> Resource View打开) 中,展开项目资源。 - 找到
Dialog文件夹,里面应该有一个以你的控件类命名的对话框资源 (如IDD_SIMPLEBUTTON),双击打开它,这个对话框模板就代表了你的 OCX 控件的可视界面。
- 在
-
设计界面:
- 从
Toolbox拖放控件到这个对话框上,为了创建一个按钮控件,拖放一个Button控件 (CButton类在 MFC/ATL 中对应)。 - 调整大小和位置,将此对话框视为控件的“画布”。
- 从
-
关联成员变量 (重要):
- 在对话框资源编辑器中,右键点击你添加的按钮控件,选择
Add Variable...。 - 在
Add Member Variable Wizard中:Variable name: 输入有意义的名称 (如m_btnClickMe)。Category: 选择Control(这是关键!区别于Value)。Control variable: 会自动选择你点击的控件类型 (如CButton)。Control ID: 自动关联。- 点击
Finish,这会在你的控件类 (CSimpleButton) 的头文件中添加一个CButton类型的成员变量m_btnClickMe,并将它与你设计的按钮资源关联起来。
- 在对话框资源编辑器中,右键点击你添加的按钮控件,选择
实现控件功能 (属性、方法、事件)
-
添加自定义属性:
- 在
Class View(可通过View -> Class View打开) 中,右键点击你的控件接口 (如ISimpleButton),选择Add -> Add Property...。 - 选择属性类型 (如
BSTR用于字符串,LONG用于整数,VARIANT_BOOL用于布尔值)。 - 输入属性名 (如
ButtonText)。 - 根据需要选择
Get和Set函数 (通常两者都选)。 - 点击
Finish,VS2010 会在控件类 (CSimpleButton) 的.cpp文件中生成存根方法 (get_ButtonText,put_ButtonText)。 - 实现属性 Get/Set:
STDMETHODIMP CSimpleButton::get_ButtonText(BSTR pVal) { // 假设 m_btnClickMe 是关联的按钮成员变量 CString strText; m_btnClickMe.GetWindowText(strText); pVal = strText.AllocSysString(); // 将 CString 转为 BSTR return S_OK; } STDMETHODIMP CSimpleButton::put_ButtonText(BSTR newVal) { CString strText(newVal); // 将 BSTR 转为 CString m_btnClickMe.SetWindowText(strText); return S_OK; }
- 在
-
添加自定义方法:
- 在
Class View中,右键点击你的控件接口 (如ISimpleButton),选择Add -> Add Method...。 - 输入方法名 (如
FlashButton)。 - 定义参数 (可选),添加
[in] LONG duration参数。 - 设置返回类型 (
HRESULT)。 - 点击
Finish,生成存根方法FlashButton。 - 实现方法:
STDMETHODIMP CSimpleButton::FlashButton(LONG duration) { // 这里实现让按钮闪烁 duration 毫秒的逻辑 // 使用定时器改变按钮背景色交替 // ... (具体实现代码) return S_OK; // 或返回错误 HRESULT }
- 在
-
触发事件 (连接点):
- 向导在添加控件时勾选了
Support Connection Points,因此生成了连接点接口 (如_ISimpleButtonEvents) 和代理类 (CProxy_ISimpleButtonEvents)。 - 在控件类中触发事件:
- 在控件类的头文件中,找到
BEGIN_CONNECTION_POINT_MAP宏,确保已包含连接点入口 (向导通常已添加好)。 - 当需要触发事件时 (在按钮的
BN_CLICKED消息处理函数中),使用Fire_XXX方法,VS2010 会在连接点接口头文件中生成这些Fire方法。 - 添加按钮点击事件处理:
- 在
Resource View中打开控件对话框 (IDD_SIMPLEBUTTON)。 - 右键点击按钮控件,选择
Add Event Handler...。 - 选择消息类型
BN_CLICKED,类列表选择你的控件类 (CSimpleButton),点击Add and Edit,生成OnBnClicked...函数。
- 在
- 在点击处理函数中触发自定义事件:
void CSimpleButton::OnBnClickedButton1() { // 假设按钮ID是IDC_BUTTON1 // 触发一个名为 'OnClick' 的事件,可以传递参数 Fire_OnClick(); // 假设你在连接点接口中添加了 OnClick 方法 // 或者带参数: Fire_OnClick(m_xPos, m_yPos); }
- 在控件类的头文件中,找到
- 在连接点接口中添加事件方法:
- 在
Class View中,右键点击_ISimpleButtonEvents接口 (它通常在Interfaces下的_ISimpleButtonEvents节点或Lib下的dispinterface节点),选择Add -> Add Method...。 - 输入事件名 (如
OnClick)。 - 定义事件参数 (可选)。
- 点击
Finish,这会更新类型库并生成对应的Fire_OnClick方法。
- 在
- 向导在添加控件时勾选了
实现 IObjectSafety (增强安全性)
勾选 Support IObjectSafety 后,向导会在控件类中自动添加 IObjectSafetyImpl 基类,你通常不需要修改其默认实现 (GetInterfaceSafetyOptions, SetInterfaceSafetyOptions),这些方法默认将控件标记为对脚本 (INTERFACESAFE_FOR_UNTRUSTED_CALLER) 和初始化 (INTERFACESAFE_FOR_UNTRUSTED_DATA) 都是安全的,这有助于浏览器信任控件。
重要安全警告: 标记为安全意味着你承诺你的控件不会执行危险操作(如删除文件、访问敏感信息),确保你的控件行为确实安全!如果控件需要执行特权操作,应明确标记为不安全,并让用户知晓风险。
编译、调试与注册

-
编译: 按
F7或选择Build -> Build Solution,确保编译成功生成.ocx文件 (在输出目录,如Debug或Release文件夹下)。 -
调试:
- OCX 是进程内组件 (DLL),需要宿主容器加载,VS2010 提供了
ActiveX Control Test Container工具。 - 在
Tools菜单下,选择ActiveX Control Test Container,如果没找到,可能需要从Tools -> Choose Toolbox Items...对话框的COM Components选项卡中找到并运行它 (搜索tstcon32.exe路径)。 - 在 Test Container 中,选择
Edit -> Insert New Control...,找到并选择你的 OCX 控件 (MyFirstOCX.SimpleButton)。 - 控件将加载到容器中,你可以:
- 查看/修改其属性 (通过容器的属性窗口)。
- 调用其方法 (通过容器的
Invoke Methods对话框)。 - 触发事件 (点击按钮),在容器的输出窗口观察事件是否被正确触发。
- 在 VS2010 中设置断点,当在 Test Container 中与控件交互时,调试器会命中断点。
- OCX 是进程内组件 (DLL),需要宿主容器加载,VS2010 提供了
-
注册 OCX:
- 开发注册: VS2010 在成功编译后通常会自动注册 OCX 到当前开发机器,检查输出窗口是否有
RegSvr32成功注册的消息。 - 手动注册:
- 以管理员身份打开
Command Prompt。 - 导航到
.ocx文件所在的目录。 - 运行命令:
regsvr32 MyFirstOCX.ocx(替换为你的实际文件名),成功会弹出提示框。
- 以管理员身份打开
- 卸载注册:
regsvr32 /u MyFirstOCX.ocx。
- 开发注册: VS2010 在成功编译后通常会自动注册 OCX 到当前开发机器,检查输出窗口是否有
部署与使用
- 打包: 将编译好的
.ocx文件 (通常是 Release 版)、依赖的运行时库 (如果使用静态链接则可能不需要) 打包。 - 目标机器注册: 在目标机器上,同样需要以管理员权限运行
regsvr32 YourOCX.ocx进行注册。 - 在 Web 中使用 (示例):
<object id="MyOCX" classid="clsid:YOUR-CONTROL-CLSID-HERE" width="200" height="50"> <param name="ButtonText" value="Click Me!" /> (Alternative content for browsers without ActiveX support) </object> <script> function buttonClicked() { alert('The OCX button was clicked!'); } // 假设你的事件接口定义了名为 'OnClick' 的事件 MyOCX.attachEvent('OnClick', buttonClicked); // IE (传统方式) // 或使用更现代(但仍有限)的 addEventListener (取决于控件实现) </script>- 将
YOUR-CONTROL-CLSID-HERE替换为你的控件实际的 CLSID (可在控件的.rgs注册脚本文件或SimpleButton_i.c文件中找到)。 - 使用
<param>标签设置初始属性。 - 使用脚本 (
attachEvent或addEventListener) 处理控件触发的事件,注意现代浏览器对 ActiveX 的限制非常严格,通常仅在 IE 兼容模式或特定企业环境中可用。
- 将
知识拓展与高级技巧
- 属性页: 为控件添加自定义属性页,方便在 VB6 或 Delphi 等设计器环境中配置属性。
- 持久性: 实现
IPersistStreamInit或IPersistPropertyBag接口,让容器能保存和加载控件的状态 (属性值)。 - 窗口化 vs 无窗口: ATL 支持创建无窗口控件 (
CComControlBase::m_bWindowOnly),可提高性能和在特定容器中的兼容性,但实现更复杂。 - 聚合与包容: 深入理解 COM 聚合模型,构建更复杂的组件关系。
- 线程模型: 理解 COM 线程模型 (
Apartment,Free等) 对控件设计和性能的影响。 - .NET 互操作: 在 .NET 应用程序中使用
COM Interop(AxHost包装器) 来承载 OCX 控件。 - 替代方案评估: 对于新项目,认真评估 .NET UserControl/WPF Custom Control 或现代 Web 组件 (Web Components) 是否更合适。
你遇到了哪个挑战?
开发 VS2010 OCX 控件需要对 COM、ATL 和 Windows GUI 编程有扎实的理解,本教程提供了核心流程和关键点,你在实践过程中遇到了哪些具体问题?是属性页的定制、无窗口控件的实现、特定容器中的兼容性问题,还是 Web 嵌入的安全限制?欢迎在评论区分享你的具体场景和遇到的障碍,共同探讨解决方案!对于复杂的遗留系统集成需求,你最终选择了 OCX 还是探索了其他替代路径?
原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/14862.html