OptionButton Control (VBCCROptionButton)
VBCCROptionButton 控件是一个单选按钮控件,允许用户从一组选项中选择一个选项。它通常与其他 OptionButton 控件一起使用,形成一个选项组。
属性
外观属性
Alignment
- 文本对齐方式vbLeftJustify
(0) - 左对齐vbRightJustify
(1) - 右对齐
Appearance
- 外观样式cc2D
(0) - 2D 外观cc3D
(1) - 3D 外观
BackColor
- 背景色ForeColor
- 文本颜色Font
- 字体属性Caption
- 按钮文本Picture
- 图标DisabledPicture
- 禁用状态图标DownPicture
- 按下状态图标Enabled
- 是否启用Visible
- 是否可见Value
- 选中状态True
- 选中False
- 未选中
ToolTipText
- 提示文本
事件
Click
- 点击时触发DblClick
- 双击时触发MouseDown
- 鼠标按下时触发MouseMove
- 鼠标移动时触发MouseUp
- 鼠标释放时触发GotFocus
- 获得焦点时触发LostFocus
- 失去焦点时触发KeyDown
- 按键按下时触发KeyPress
- 按键时触发KeyUp
- 按键释放时触发
代码示例
基本用法
vb
Private Sub InitOptionButtons()
' 设置基本属性
With Option1
.Caption = "选项 1"
.Value = True ' 默认选中
.ToolTipText = "这是第一个选项"
End With
With Option2
.Caption = "选项 2"
.Value = False
.ToolTipText = "这是第二个选项"
End With
End Sub
选项组管理
vb
Private Type OptionGroup
Name As String
Buttons() As VBCCROptionButton
Count As Long
SelectedIndex As Long
End Type
Private Type GroupManager
Groups() As OptionGroup
Count As Long
End Type
Private Groups As GroupManager
Private Sub InitGroupManager()
ReDim Groups.Groups(1 To 10)
Groups.Count = 0
End Sub
Private Function CreateOptionGroup(ByVal Name As String) As Long
With Groups
.Count = .Count + 1
If .Count > UBound(.Groups) Then
ReDim Preserve .Groups(1 To .Count + 10)
End If
With .Groups(.Count)
.Name = Name
ReDim .Buttons(1 To 10)
.Count = 0
.SelectedIndex = -1
End With
CreateOptionGroup = .Count
End With
End Function
Private Sub AddToGroup(ByVal GroupIndex As Long, _
ByVal Button As VBCCROptionButton)
If GroupIndex < 1 Or GroupIndex > Groups.Count Then Exit Sub
With Groups.Groups(GroupIndex)
.Count = .Count + 1
If .Count > UBound(.Buttons) Then
ReDim Preserve .Buttons(1 To .Count + 10)
End If
Set .Buttons(.Count) = Button
' 设置标签以标识组和索引
Button.Tag = GroupIndex & ":" & .Count
' 添加事件处理
Button.Value = False ' 确保初始状态为未选中
End With
End Sub
Private Sub OptionButton_Click()
Dim Button As VBCCROptionButton
Set Button = Me.ActiveControl
' 解析组和索引
Dim Parts() As String
Parts = Split(Button.Tag, ":")
If UBound(Parts) <> 1 Then Exit Sub
Dim GroupIndex As Long
Dim ButtonIndex As Long
GroupIndex = Val(Parts(0))
ButtonIndex = Val(Parts(1))
UpdateGroupSelection GroupIndex, ButtonIndex
End Sub
Private Sub UpdateGroupSelection(ByVal GroupIndex As Long, _
ByVal ButtonIndex As Long)
If GroupIndex < 1 Or GroupIndex > Groups.Count Then Exit Sub
With Groups.Groups(GroupIndex)
' 取消之前的选择
If .SelectedIndex > 0 Then
.Buttons(.SelectedIndex).Value = False
End If
' 更新选择
.SelectedIndex = ButtonIndex
.Buttons(ButtonIndex).Value = True
' 触发选择变更事件
RaiseEvent GroupSelectionChanged GroupIndex, ButtonIndex
End With
End Sub
Private Function GetSelectedOption(ByVal GroupIndex As Long) As Long
If GroupIndex < 1 Or GroupIndex > Groups.Count Then
GetSelectedOption = -1
Exit Function
End If
GetSelectedOption = Groups.Groups(GroupIndex).SelectedIndex
End Function
动态选项按钮
vb
Private Type DynamicOption
Button As VBCCROptionButton
Value As Variant
Enabled As Boolean
Visible As Boolean
Tag As Variant
End Type
Private Type OptionSet
Name As String
Options() As DynamicOption
Count As Long
Container As Object ' Frame or PictureBox
ItemHeight As Single
ItemSpacing As Single
End Type
Private Type SetManager
Sets() As OptionSet
Count As Long
End Type
Private Sets As SetManager
Private Sub InitSetManager()
ReDim Sets.Sets(1 To 10)
Sets.Count = 0
End Sub
Private Function CreateOptionSet(ByVal Name As String, _
ByVal Container As Object, _
Optional ByVal ItemHeight As Single = 300, _
Optional ByVal ItemSpacing As Single = 60) _
As Long
With Sets
.Count = .Count + 1
If .Count > UBound(.Sets) Then
ReDim Preserve .Sets(1 To .Count + 10)
End If
With .Sets(.Count)
.Name = Name
Set .Container = Container
.ItemHeight = ItemHeight
.ItemSpacing = ItemSpacing
ReDim .Options(1 To 10)
.Count = 0
End With
CreateOptionSet = .Count
End With
End Function
Private Sub AddOption(ByVal SetIndex As Long, _
ByVal Caption As String, _
Optional ByVal Value As Variant = Empty)
If SetIndex < 1 Or SetIndex > Sets.Count Then Exit Sub
With Sets.Sets(SetIndex)
.Count = .Count + 1
If .Count > UBound(.Options) Then
ReDim Preserve .Options(1 To .Count + 10)
End If
With .Options(.Count)
' 创建新的选项按钮
Set .Button = Controls.Add("VBCCROptionButton", _
"Option" & SetIndex & "_" & Sets.Sets(SetIndex).Count)
' 设置位置和大小
With .Button
.Container = Sets.Sets(SetIndex).Container
.Caption = Caption
.Top = (Sets.Sets(SetIndex).Count - 1) * _
(Sets.Sets(SetIndex).ItemHeight + Sets.Sets(SetIndex).ItemSpacing)
.Height = Sets.Sets(SetIndex).ItemHeight
.Width = Sets.Sets(SetIndex).Container.ScaleWidth
.Left = 0
.Visible = True
End With
' 保存值
If IsEmpty(Value) Then
.Value = Caption
Else
.Value = Value
End If
.Enabled = True
.Visible = True
End With
End With
' 调整容器高度
AdjustContainerHeight SetIndex
End Sub
Private Sub AdjustContainerHeight(ByVal SetIndex As Long)
If SetIndex < 1 Or SetIndex > Sets.Count Then Exit Sub
With Sets.Sets(SetIndex)
.Container.Height = .Count * (.ItemHeight + .ItemSpacing)
End With
End Sub
Private Sub RemoveOption(ByVal SetIndex As Long, _
ByVal OptionIndex As Long)
If SetIndex < 1 Or SetIndex > Sets.Count Then Exit Sub
If OptionIndex < 1 Or OptionIndex > Sets.Sets(SetIndex).Count Then Exit Sub
With Sets.Sets(SetIndex)
' 移除控件
Controls.Remove .Options(OptionIndex).Button.Name
' 移动后续选项
Dim i As Long
For i = OptionIndex To .Count - 1
Set .Options(i) = .Options(i + 1)
' 更新位置
With .Options(i).Button
.Top = (i - 1) * _
(Sets.Sets(SetIndex).ItemHeight + Sets.Sets(SetIndex).ItemSpacing)
End With
Next i
' 减少计数
.Count = .Count - 1
' 调整容器大小
AdjustContainerHeight SetIndex
End With
End Sub
Private Function GetSelectedValue(ByVal SetIndex As Long) As Variant
If SetIndex < 1 Or SetIndex > Sets.Count Then
GetSelectedValue = Empty
Exit Function
End If
With Sets.Sets(SetIndex)
Dim i As Long
For i = 1 To .Count
If .Options(i).Button.Value Then
GetSelectedValue = .Options(i).Value
Exit Function
End If
Next i
End With
GetSelectedValue = Empty
End Function
数据绑定
vb
Private Type BoundOption
Button As VBCCROptionButton
DataField As String
DataSource As Object ' Recordset or Collection
End Type
Private Type BindingManager
Bindings() As BoundOption
Count As Long
End Type
Private Bindings As BindingManager
Private Sub InitBindingManager()
ReDim Bindings.Bindings(1 To 10)
Bindings.Count = 0
End Sub
Private Function BindOptionToData(ByVal Button As VBCCROptionButton, _
ByVal DataSource As Object, _
ByVal DataField As String) As Long
With Bindings
.Count = .Count + 1
If .Count > UBound(.Bindings) Then
ReDim Preserve .Bindings(1 To .Count + 10)
End If
With .Bindings(.Count)
Set .Button = Button
Set .DataSource = DataSource
.DataField = DataField
' 初始化值
UpdateOptionFromData .Count
End With
BindOptionToData = .Count
End With
End Function
Private Sub UpdateOptionFromData(ByVal BindingIndex As Long)
If BindingIndex < 1 Or BindingIndex > Bindings.Count Then Exit Sub
With Bindings.Bindings(BindingIndex)
If TypeOf .DataSource Is ADODB.Recordset Then
' ADO Recordset
If Not .DataSource.EOF Then
.Button.Value = .DataSource.Fields(.DataField).Value
End If
ElseIf TypeOf .DataSource Is Collection Then
' Collection
If .DataSource.Count > 0 Then
.Button.Value = .DataSource.Item(.DataField)
End If
End If
End With
End Sub
Private Sub UpdateDataFromOption(ByVal BindingIndex As Long)
If BindingIndex < 1 Or BindingIndex > Bindings.Count Then Exit Sub
With Bindings.Bindings(BindingIndex)
If TypeOf .DataSource Is ADODB.Recordset Then
' ADO Recordset
If Not .DataSource.EOF Then
.DataSource.Fields(.DataField).Value = .Button.Value
End If
ElseIf TypeOf .DataSource Is Collection Then
' Collection
If .DataSource.Count > 0 Then
.DataSource.Item(.DataField) = .Button.Value
End If
End If
End With
End Sub
Private Sub BoundOption_Click()
Dim Button As VBCCROptionButton
Set Button = Me.ActiveControl
' 查找绑定
Dim i As Long
For i = 1 To Bindings.Count
If Bindings.Bindings(i).Button Is Button Then
UpdateDataFromOption i
Exit For
End If
Next i
End Sub
分页选项
vb
Private Type PagedOptions
Name As String
Options() As VBCCROptionButton
Count As Long
PageSize As Long
CurrentPage As Long
Container As Object
ItemHeight As Single
ItemSpacing As Single
End Type
Private Type PageManager
Pages() As PagedOptions
Count As Long
End Type
Private Pages As PageManager
Private Sub InitPageManager()
ReDim Pages.Pages(1 To 10)
Pages.Count = 0
End Sub
Private Function CreatePagedOptions(ByVal Name As String, _
ByVal Container As Object, _
Optional ByVal PageSize As Long = 10, _
Optional ByVal ItemHeight As Single = 300, _
Optional ByVal ItemSpacing As Single = 60) _
As Long
With Pages
.Count = .Count + 1
If .Count > UBound(.Pages) Then
ReDim Preserve .Pages(1 To .Count + 10)
End If
With .Pages(.Count)
.Name = Name
Set .Container = Container
.PageSize = PageSize
.ItemHeight = ItemHeight
.ItemSpacing = ItemSpacing
ReDim .Options(1 To PageSize)
.Count = 0
.CurrentPage = 1
End With
CreatePagedOptions = .Count
End With
End Function
Private Sub AddPagedOption(ByVal PageIndex As Long, _
ParamArray Options() As Variant)
If PageIndex < 1 Or PageIndex > Pages.Count Then Exit Sub
With Pages.Pages(PageIndex)
Dim i As Long
For i = LBound(Options) To UBound(Options)
If .Count = UBound(.Options) Then
ReDim Preserve .Options(1 To .Count + .PageSize)
End If
.Count = .Count + 1
' 创建选项按钮
Set .Options(.Count) = Controls.Add("VBCCROptionButton", _
.Name & "_Option" & .Count)
With .Options(.Count)
.Container = Pages.Pages(PageIndex).Container
.Caption = Options(i)
.Visible = False ' 初始化时隐藏
End With
Next i
' 显示当前页
ShowPage PageIndex, .CurrentPage
End With
End Sub
Private Sub ShowPage(ByVal PageIndex As Long, _
ByVal PageNumber As Long)
If PageIndex < 1 Or PageIndex > Pages.Count Then Exit Sub
With Pages.Pages(PageIndex)
' 隐藏所有选项
Dim i As Long
For i = 1 To .Count
.Options(i).Visible = False
Next i
' 计算页范围
Dim StartIndex As Long
Dim EndIndex As Long
StartIndex = (PageNumber - 1) * .PageSize + 1
EndIndex = StartIndex + .PageSize - 1
If EndIndex > .Count Then EndIndex = .Count
' 显示当前页的选项
For i = StartIndex To EndIndex
With .Options(i)
.Top = (i - StartIndex) * _
(Pages.Pages(PageIndex).ItemHeight + _
Pages.Pages(PageIndex).ItemSpacing)
.Width = Pages.Pages(PageIndex).Container.ScaleWidth
.Left = 0
.Visible = True
End With
Next i
.CurrentPage = PageNumber
End With
End Sub
Private Function GetPageCount(ByVal PageIndex As Long) As Long
If PageIndex < 1 Or PageIndex > Pages.Count Then
GetPageCount = 0
Exit Function
End If
With Pages.Pages(PageIndex)
GetPageCount = (.Count + .PageSize - 1) \ .PageSize
End With
End Function
Private Sub NextPage(ByVal PageIndex As Long)
If PageIndex < 1 Or PageIndex > Pages.Count Then Exit Sub
With Pages.Pages(PageIndex)
If .CurrentPage < GetPageCount(PageIndex) Then
ShowPage PageIndex, .CurrentPage + 1
End If
End With
End Sub
Private Sub PreviousPage(ByVal PageIndex As Long)
If PageIndex < 1 Or PageIndex > Pages.Count Then Exit Sub
With Pages.Pages(PageIndex)
If .CurrentPage > 1 Then
ShowPage PageIndex, .CurrentPage - 1
End If
End With
End Sub
最佳实践
- 错误处理
vb
Private Sub SafeSetOptionValue(ByVal Button As VBCCROptionButton, _
ByVal Value As Boolean)
On Error GoTo ErrorHandler
Button.Value = Value
Exit Sub
ErrorHandler:
Debug.Print "设置选项按钮值失败: " & Err.Description
End Sub
- 快捷键支持
vb
Private Sub SetOptionHotkey(ByVal Button As VBCCROptionButton, _
ByVal Key As Integer, _
Optional ByVal Ctrl As Boolean = False, _
Optional ByVal Alt As Boolean = False, _
Optional ByVal Shift As Boolean = False)
' 添加快捷键提示
Dim HotkeyText As String
If Ctrl Then HotkeyText = HotkeyText & "Ctrl+"
If Alt Then HotkeyText = HotkeyText & "Alt+"
If Shift Then HotkeyText = HotkeyText & "Shift+"
HotkeyText = HotkeyText & Chr$(Key)
Button.ToolTipText = Button.Caption & " (" & HotkeyText & ")"
' 保存快捷键信息
Button.Tag = Key & ":" & Ctrl & ":" & Alt & ":" & Shift
End Sub
- 状态保存
vb
Private Sub SaveOptionState(ByVal Button As VBCCROptionButton)
SaveSetting App.Title, Button.Name, "Caption", Button.Caption
SaveSetting App.Title, Button.Name, "Value", Button.Value
SaveSetting App.Title, Button.Name, "Enabled", Button.Enabled
SaveSetting App.Title, Button.Name, "Visible", Button.Visible
SaveSetting App.Title, Button.Name, "Tag", Button.Tag
End Sub
Private Sub RestoreOptionState(ByVal Button As VBCCROptionButton)
With Button
.Caption = GetSetting(App.Title, .Name, "Caption", .Caption)
.Value = CBool(GetSetting(App.Title, .Name, "Value", .Value))
.Enabled = CBool(GetSetting(App.Title, .Name, "Enabled", .Enabled))
.Visible = CBool(GetSetting(App.Title, .Name, "Visible", .Visible))
.Tag = GetSetting(App.Title, .Name, "Tag", .Tag)
End With
End Sub
OptionButton 控件是实现单选功能的重要控件,通过合理组织和管理,可以实现灵活的选项分组、数据绑定和分页显示等功能。上述示例展示了 OptionButton 控件的多种用法,开发者可以根据实际需求选择合适的实现方式。