在 C# 程序中使用 OCX(ActiveX)控件是一个相对直接的过程。微软提供了很好的互操作性支持。
以下是详细的方法和步骤。
核心原理
C# 通过 "运行时可调用包装" 将 COM 组件(如 OCX)包装成 .NET 能够识别和使用的类。我们不需要直接与复杂的 COM 接口打交道。
详细步骤
以下以使用一个假设的 "MyCalendar.ocx" 控件为例。
步骤 1:确保 OCX 已注册
在引用之前,必须先将 OCX 控件注册到系统中。
以 管理员身份 打开命令提示符。
使用 regsvr32 命令注册:regsvr32 "C:\Path\To\Your\MyCalendar.ocx"
如果看到成功提示,则说明注册成功。
注意:对于 32 位 OCX 在 64 位系统上,通常应将其复制到 C:\Windows\SysWOW64\ 目录,并使用该目录下的 regsvr32.exe 进行注册。
步骤 2:在 Visual Studio 中添加引用
这是最关键的一步,让我们的 C# 项目能够"看到"这个 OCX 控件。
在 解决方案资源管理器 中,右键点击项目的 "引用"。
选择 "添加引用"。
在弹出的窗口中,切换到 "COM" 选项卡。
在列表中找到我们的 OCX 控件。它通常以其在注册表中的描述性名称显示(例如,"MyCalendar Control")。如果找不到,可以点击 "浏览..." 按钮,直接定位到我们的 .ocx 文件。
选中它并点击 "确定"。
完成后会发生什么?
Visual Studio 会自动做两件事:
为我们的 OCX 控件生成一个 主互操作程序集,通常名为 Interop.ControlName.dll。
生成一个 Windows Forms 包装器,通常名为 AxInterop.ControlName.dll。这个 Ax 开头的 DLL 才是我们在 WinForms 设计中可以直接拖放的控件。
步骤 3:在窗体设计器中使用(拖放方式)
这是最简单、最直观的方法,适用于 Windows Forms 应用程序。
打开我们的 WinForms 窗体(如 Form1.cs 的设计视图)。
在 工具箱 中,我们应该会看到一个新的分组,里面包含了我们的 OCX 控件(例如,"AxMyCalendar")。
如果没看到,可以右键工具箱 -> "选择项..." -> 在 "COM 组件" 选项卡中找到并勾选我们的控件。
将这个控件从工具箱 拖拽 到我们的窗体上。
自动生成代码:Visual Studio 会自动在 Form1.Designer.cs 文件中生成相应的代码:
// Form1.Designer.cs
private AxMyCalendarLib.AxMyCalendar axMyCalendar1;
private void InitializeComponent()
{
this.axMyCalendar1 = new AxMyCalendarLib.AxMyCalendar();
((System.ComponentModel.ISupportInitialize)(this.axMyCalendar1)).BeginInit();
// ... 其他初始化代码
this.Controls.Add(this.axMyCalendar1);
// ... 其他初始化代码
((System.ComponentModel.ISupportInitialize)(this.axMyCalendar1)).EndInit();
}
步骤 4:通过代码动态创建
如果我们需要更灵活地控制,或者是在非 WinForms 项目(如 WPF)中使用,可以通过代码动态创建。
在 Windows Forms 中:
public partial class Form1 : Form
{
private AxMyCalendarLib.AxMyCalendar myCalendar;
public Form1()
{
InitializeComponent();
// 动态创建控件实例
myCalendar = new AxMyCalendarLib.AxMyCalendar();
((System.ComponentModel.ISupportInitialize)myCalendar).BeginInit();
// 设置属性
myCalendar.Location = new Point(10, 10);
myCalendar.Size = new Size(500, 300);
myCalendar.BackColor = Color.White;
// 添加到窗体
this.Controls.Add(myCalendar);
((System.ComponentModel.ISupportInitialize)myCalendar).EndInit();
// 订阅事件
myCalendar.DateChange += new EventHandler(MyCalendar_DateChange);
}
private void MyCalendar_DateChange(object sender, EventArgs e)
{
// 处理日期改变事件
MessageBox.Show($"选择的日期是:{myCalendar.Value}");
}
}
在 WPF 中(使用 WindowsFormsHost):
WPF 不能直接承载 ActiveX 控件,需要使用 WindowsFormsHost 作为桥梁。
添加对 System.Windows.Forms 和 WindowsFormsIntegration 的引用。
在 XAML 中: xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" xmlns:ax="clr-namespace:AxMyCalendarLib;assembly=AxInterop.MyCalendarLib">
或者在代码后台中动态创建。
步骤 5:使用控件功能
一旦控件被添加到窗体,我们就可以像使用任何其他 .NET 控件一样使用它:
设置/获取属性:
axMyCalendar1.SelectedDate = DateTime.Now;
DateTime selectedDate = axMyCalendar1.Value;
调用方法:
axMyCalendar1.NextMonth();
处理事件:在属性窗口的事件列表中找到事件,双击即可生成事件处理程序。
常见问题与解决方案
1. "无法嵌入互操作类型" 错误
错误信息:无法嵌入互操作类型‘XXX’。请改用适用的接口。
解决方案:
在解决方案资源管理器中,找到对应的 COM 引用(如 Interop.MyCalendarLib)。
右键点击它,选择 "属性"。
在属性窗口中,将 "嵌入互操作类型" 设置为 False。
2. 部署问题(在客户机上运行)
我们的程序在开发机器上运行良好,但在客户机上报错,提示找不到控件或类未注册。
解决方案:
确保 OCX 文件存在并已注册:这是最常见的原因。我们需要确保目标机器上已经用 regsvr32 注册了 OCX 文件。
包含互操作程序集:确保生成的 Interop.XXX.dll 和 AxInterop.XXX.dll 随我们的应用程序一起发布。
使用安装项目:对于正式部署,建议创建一个安装项目(如 ClickOnce 或 MSI),在安装过程中自动注册 OCX 控件。
3. 线程问题
重要:与 ActiveX 控件的所有交互都必须在创建它的线程上执行(通常是 UI 主线程)。如果我们在后台线程中操作控件,需要使用 Control.Invoke 方法。
// 在后台线程中更新控件
if (axMyCalendar1.InvokeRequired)
{
axMyCalendar1.Invoke(new Action(() => {
axMyCalendar1.Value = DateTime.Now;
}));
}
else
{
axMyCalendar1.Value = DateTime.Now;
}
总结
步骤
核心操作
说明
1
注册 OCX
使用 regsvr32 命令在系统中注册控件。
2
添加 COM 引用
在 VS 中通过 "添加引用" -> "COM" 引入控件。
3
使用控件
设计时:从工具箱拖放。运行时:通过代码 new 创建。
4
编程
像普通 .NET 控件一样设置属性、调用方法、处理事件。
5
部署
确保目标机器上有 OCX 文件并已注册,同时带上互操作 DLL。
虽然 OCX/ActiveX 是一项老旧技术,但通过 .NET 的互操作层,在 C# 中使用它们仍然非常方便,尤其是在维护遗留系统或使用一些没有 .NET 替代品的专用控件时。