睿诚科技协会

ActiveX控件中引入窗体技术有何优势?

为什么要在 ActiveX 控件中使用窗体?

想象一下,一个 ActiveX 控件本身就像一个“黑盒子”,它可以在容器(如 Word 或 VB6 窗体)上绘制界面并响应事件,但这个界面通常很有限,比如只能是一个按钮、一个文本框或一个绘图区域。

ActiveX控件中引入窗体技术有何优势?-图1
(图片来源网络,侵删)

当你的控件需要提供一个更复杂的、独立的用户界面时,比如一个设置面板、一个数据配置向导、一个属性对话框,或者一个复杂的编辑器界面时,就需要一个独立的窗体。

引入窗体技术的核心目的就是:

  1. 提供丰富的用户交互界面: 独立的窗体可以使用标准的 Windows 控件(如 TextBox, ListBox, TreeView, TabStrip 等),构建出比控件本身主界面复杂得多的 UI。
  2. 封装复杂的逻辑: 将与这个 UI 相关的所有逻辑、数据操作和状态管理都封装在窗体内,保持 ActiveX 控件本身的简洁。
  3. 提供模态或非模态的交互体验:
    • 模态窗体: 用户必须先操作完这个窗体(比如点击“确定”或“取消”)才能返回到主容器应用程序,常用于设置、确认等场景。
    • 非模态窗体: 窗体打开后,用户可以同时与主容器和其他应用程序交互,常用于工具窗口、实时监控面板等。
  4. 解耦界面与控件: 窗体可以独立于 ActiveX 控件进行设计、修改和测试,提高了代码的可维护性。

实现步骤详解 (以 Visual Basic 6.0 为例)

VB6 是实现这项技术最经典、最直观的工具,下面我们以创建一个名为 MyOCX 的 ActiveX 控件为例,讲解如何为其添加一个设置窗体。

步骤 1:创建 ActiveX 控件工程

  1. 打开 VB6,选择 "ActiveX 控件" (ActiveX Control)。
  2. 保存工程,
    • 工程名: MyOCXProj
    • 控件文件名: MyOCX.ctl
    • 工程组名: MyOCXGroup

步骤 2:设计 ActiveX 控件的主界面

MyOCX.ctl 的设计视图中,放置一个简单的命令按钮 cmdShowSettings,这个按钮将作为触发设置窗体的入口。

ActiveX控件中引入窗体技术有何优势?-图2
(图片来源网络,侵删)
' MyOCX.ctl
Private Sub cmdShowSettings_Click()
    ' 在这里我们将编写代码来显示窗体
End Sub

步骤 3:添加标准窗体

  1. 在 "工程" 菜单中,选择 "添加窗体" (Add Form)。
  2. 选择 “标准 EXE” 窗体 (Standard EXE),点击“打开”。
  3. 保存这个新窗体,frmSettings.frm
  4. frmSettings 上设计你的设置界面,
    • 一个文本框 txtUserName
    • 一个复选框 chkAutoSave
    • 两个命令按钮 cmdOKcmdCancel

步骤 4:建立 ActiveX 控件与窗体的连接

这是最关键的一步,我们需要让 MyOCX 控件能够创建并显示 frmSettings 窗体,并且能够从窗体中获取用户设置的数据。

直接创建(简单直接)

MyOCX 控件的代码中,直接实例化并显示窗体。

' MyOCX.ctl 的代码
' 需要在控件的通用声明部分添加一个对设置窗体的引用
' Private m_frmSettings As frmSettings
Private Sub cmdShowSettings_Click()
    ' 检查窗体是否已经实例化,避免重复创建
    If m_frmSettings Is Nothing Then
        Set m_frmSettings = New frmSettings
    End If
    ' 将当前控件的设置传递给窗体,以便窗体能显示正确的初始值
    m_frmSettings.txtUserName.Text = m_strUserName
    m_frmSettings.chkAutoSave.Value = m_blnAutoSave
    ' 以模态方式显示窗体
    ' vbModal 表示这是一个模态窗体
    m_frmSettings.Show vbModal
    ' 当窗体关闭后(用户点击了确定或取消),可以在这里获取新值
    If m_frmSettings.DialogResult = vbOK Then ' 假设我们在窗体中定义了 DialogResult
        m_strUserName = m_frmSettings.txtUserName.Text
        m_blnAutoSave = (m_frmSettings.chkAutoSave.Value = vbChecked)
        ' 可以在这里触发一个事件,通知容器控件的属性已更改
        PropertyChanged "UserName"
        PropertyChanged "AutoSave"
    End If
    ' 释放窗体对象
    Set m_frmSettings = Nothing
End Sub
' 控件的属性(需要用 Public Property Get/Let 声明)
Private m_strUserName As String
Public Property Get UserName() As String
    UserName = m_strUserName
End Property
Public Property Let UserName(ByVal vNewValue As String)
    m_strUserName = vNewValue
End Property
Private m_blnAutoSave As Boolean
Public Property Get AutoSave() As Boolean
    AutoSave = m_blnAutoSave
End Property
Public Property Let AutoSave(ByVal vNewValue As Boolean)
    m_blnAutoSave = vNewValue
End Property

frmSettings.frm 中需要添加的代码:

ActiveX控件中引入窗体技术有何优势?-图3
(图片来源网络,侵删)
' frmSettings.frm 的代码
' 在窗体级别声明一个变量来记录用户点击了哪个按钮
Public DialogResult As VbMsgBoxResult
Private Sub cmdOK_Click()
    ' 用户点击了“确定”,设置 DialogResult 并关闭窗体
    DialogResult = vbOK
    Unload Me
End Sub
Private Sub cmdCancel_Click()
    ' 用户点击了“取消”,设置 DialogResult 并关闭窗体
    DialogResult = vbCancel
    Unload Me
End Sub
' 可选:当用户点击窗体右上角的 'X' 时,也视为取消
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    If UnloadMode = vbFormControlMenu Then
        DialogResult = vbCancel
    End If
End Sub

通过外接程序(更专业)

VB6 有一个 "外接程序" -> "外接程序管理器" -> "VB 6 ActiveX 控件接口向导",这个工具可以帮你更规范地定义控件的属性、方法和事件,当你通过向导添加一个属性时,它会自动生成 Property Let/Get 的骨架,你只需要在 Let 方法中调用 PropertyChanged 即可,这与方法一的核心逻辑类似,但流程更标准化。


关键技术与注意事项

  1. 线程模型:

    • ActiveX 控件和它创建的窗体必须在同一个线程上运行
    • 在 VB6 中,这通常是自动处理的,因为默认是单线程单元模型。
    • 在更现代的 .NET WinForms 或 WPF 中,如果你要将一个 ActiveX 控件嵌入其中,或者反之,必须特别注意跨线程调用问题,通常需要使用 Control.InvokeDispatcher 来确保 UI 操作在正确的线程上执行。
  2. 生命周期管理:

    • 谁创建,谁销毁:ActiveX 控件负责创建窗体实例,也必须在窗体关闭后负责将其设置为 Nothing,以释放内存,防止内存泄漏。
    • 避免全局窗体:不要将窗体声明为 GlobalPublic 在整个工程级别,这会导致多个控件实例共享同一个窗体对象,引发混乱,每个控件实例都应该拥有自己独立的窗体实例。
  3. 数据通信:

    • 属性传递:最常见的方式是,在显示窗体前,将控件的内部属性值传递给窗体的控件作为初始值,在窗体关闭后,再将窗体控件的新值回传给控件的属性。
    • 自定义事件:当窗体中的操作需要影响容器或进行复杂通知时,可以在 ActiveX 控件中定义自定义事件,窗体通过一个对控件的引用来触发这个事件,窗体中的“应用”按钮可以触发一个 ApplySettings 事件。
  4. 部署问题:

    • ActiveX 控件(.ocx 文件)和它依赖的所有窗体、模块、图片等资源,最终都会被编译进 .ocx 文件中。
    • 部署时只需要将 .ocx 文件和它的依赖库(如 MSVBVM60.DLL)一起打包,并正确注册即可,用户不需要额外安装你的 VB6 工
分享:
扫描分享到社交APP
上一篇
下一篇