ImageCombo Control (VBCCRImageCombo)
ImageCombo 控件是一个带有图像的组合框控件,它可以在每个列表项的旁边显示一个图像。这个控件通常与 ImageList 控件配合使用,用于创建更直观的下拉列表。
属性
基本属性
Text
- 当前选择的项的文本List
- 列表项集合ListCount
- 列表项数量ListIndex
- 当前选中项的索引BackColor
- 背景颜色ForeColor
- 前景颜色Enabled
- 是否启用控件Font
- 字体设置Visible
- 是否可见
图像相关属性
ImageList
- 关联的图像列表控件Images
- 项目关联的图像集合IndentLevel
- 缩进级别ItemData
- 项目关联的数值数据SelImage
- 选中时的图像索引Image
- 默认图像索引
事件
Change
- 选择改变时触发Click
- 点击控件时触发DblClick
- 双击控件时触发DropDown
- 下拉列表时触发GotFocus
- 获得焦点时触发KeyDown
- 按下键盘时触发KeyPress
- 键盘按键时触发KeyUp
- 释放键盘时触发LostFocus
- 失去焦点时触发MouseDown
- 鼠标按下时触发MouseMove
- 鼠标移动时触发MouseUp
- 鼠标释放时触发Scroll
- 滚动列表时触发CloseUp
- 关闭下拉列表时触发
代码示例
基本用法
vb
Private Sub InitImageCombo()
' 设置图像列表
Set ImageCombo1.ImageList = ImageList1
' 添加项目
With ImageCombo1
.AddItem "文档"
.ListImages(0).Picture = 1 ' 文档图标
.AddItem "图片"
.ListImages(1).Picture = 2 ' 图片图标
.AddItem "音乐"
.ListImages(2).Picture = 3 ' 音乐图标
End With
End Sub
树形菜单实现
vb
Private Type MenuItem
Text As String
ImageIndex As Long
SelImageIndex As Long
Level As Long
Tag As String
SubItems() As Long ' 子项索引数组
SubItemCount As Long
ParentIndex As Long
End Type
Private Type MenuManager
Items() As MenuItem
Count As Long
ImageList As ImageList
End Type
Private Menu As MenuManager
Private Sub InitMenuManager()
With Menu
ReDim .Items(1 To 100)
.Count = 0
Set .ImageList = ImageList1
End With
End Sub
Private Function AddMenuItem(ByVal Text As String, _
ByVal ImageIndex As Long, _
Optional ByVal SelImageIndex As Long = -1, _
Optional ByVal Level As Long = 0, _
Optional ByVal ParentIndex As Long = 0) As Long
With Menu
.Count = .Count + 1
With .Items(.Count)
.Text = Text
.ImageIndex = ImageIndex
.SelImageIndex = IIf(SelImageIndex = -1, ImageIndex, SelImageIndex)
.Level = Level
.ParentIndex = ParentIndex
ReDim .SubItems(1 To 10)
.SubItemCount = 0
' 如果有父项,添加到父项的子项列表
If ParentIndex > 0 Then
With Menu.Items(ParentIndex)
.SubItemCount = .SubItemCount + 1
If .SubItemCount > UBound(.SubItems) Then
ReDim Preserve .SubItems(1 To .SubItemCount + 10)
End If
.SubItems(.SubItemCount) = Menu.Count
End With
End If
End With
AddMenuItem = .Count
End With
End Sub
Private Sub UpdateComboItems()
With ImageCombo1
' 清空列表
Do While .ListCount > 0
.RemoveItem 0
Loop
' 添加所有项目
Dim i As Long
For i = 1 To Menu.Count
With Menu.Items(i)
' 添加项目
ImageCombo1.AddItem Space$(.Level * 4) & .Text
ImageCombo1.ListImages(ImageCombo1.ListCount - 1).Picture = .ImageIndex
End With
Next i
End With
End Sub
Private Function FindItemByText(ByVal Text As String, _
Optional ByVal ExactMatch As Boolean = True) As Long
Dim i As Long
For i = 1 To Menu.Count
If ExactMatch Then
If Menu.Items(i).Text = Text Then
FindItemByText = i
Exit Function
End If
Else
If InStr(1, Menu.Items(i).Text, Text, vbTextCompare) > 0 Then
FindItemByText = i
Exit Function
End If
End If
Next i
FindItemByText = 0
End Function
Private Sub GetSubItems(ByVal Index As Long, ByRef Results() As Long)
If Index < 1 Or Index > Menu.Count Then Exit Sub
With Menu.Items(Index)
If .SubItemCount > 0 Then
ReDim Results(1 To .SubItemCount)
Dim i As Long
For i = 1 To .SubItemCount
Results(i) = .SubItems(i)
Next i
Else
ReDim Results(0)
End If
End With
End Sub
数据绑定
vb
Private Type ItemData
ID As Long
Text As String
ImageIndex As Long
ExtraData As String
End Type
Private Type DataManager
Items() As ItemData
Count As Long
ImageList As ImageList
End Type
Private Data As DataManager
Private Sub InitDataManager()
With Data
ReDim .Items(1 To 100)
.Count = 0
Set .ImageList = ImageList1
End With
End Sub
Private Sub AddDataItem(ByVal ID As Long, _
ByVal Text As String, _
ByVal ImageIndex As Long, _
Optional ByVal ExtraData As String = "")
With Data
.Count = .Count + 1
If .Count > UBound(.Items) Then
ReDim Preserve .Items(1 To .Count + 100)
End If
With .Items(.Count)
.ID = ID
.Text = Text
.ImageIndex = ImageIndex
.ExtraData = ExtraData
End With
End With
End Sub
Private Sub BindData()
With ImageCombo1
' 清空列表
Do While .ListCount > 0
.RemoveItem 0
Loop
' 添加数据项
Dim i As Long
For i = 1 To Data.Count
With Data.Items(i)
ImageCombo1.AddItem .Text
ImageCombo1.ListImages(ImageCombo1.ListCount - 1).Picture = .ImageIndex
ImageCombo1.ItemData(ImageCombo1.ListCount - 1) = .ID
End With
Next i
End With
End Sub
Private Function FindDataById(ByVal ID As Long) As Long
Dim i As Long
For i = 1 To Data.Count
If Data.Items(i).ID = ID Then
FindDataById = i
Exit Function
End If
Next i
FindDataById = 0
End Function
Private Sub ImageCombo1_Click()
' 获取选中项的数据
If ImageCombo1.ListIndex >= 0 Then
Dim ID As Long
ID = ImageCombo1.ItemData(ImageCombo1.ListIndex)
Dim Index As Long
Index = FindDataById(ID)
If Index > 0 Then
With Data.Items(Index)
Debug.Print "选中项: " & .Text
Debug.Print "ID: " & .ID
Debug.Print "额外数据: " & .ExtraData
End With
End If
End If
End Sub
自动完成功能
vb
Private Type AutoComplete
Enabled As Boolean
Timer As VBCCRTimer
LastInput As String
MatchCase As Boolean
MinChars As Long
End Type
Private AC As AutoComplete
Private Sub InitAutoComplete()
With AC
.Enabled = True
Set .Timer = Timer1
.Timer.Interval = 500 ' 500毫秒延迟
.Timer.Enabled = False
.LastInput = ""
.MatchCase = False
.MinChars = 2
End With
End Sub
Private Sub ImageCombo1_KeyPress(KeyAscii As Integer)
If Not AC.Enabled Then Exit Sub
' 记录输入
AC.LastInput = AC.LastInput & Chr$(KeyAscii)
' 重置计时器
AC.Timer.Enabled = False
AC.Timer.Enabled = True
End Sub
Private Sub Timer1_Timer()
AC.Timer.Enabled = False
' 执行自动完成
If Len(AC.LastInput) >= AC.MinChars Then
Dim Found As Boolean
Found = False
' 查找匹配项
Dim i As Long
For i = 0 To ImageCombo1.ListCount - 1
Dim ItemText As String
ItemText = ImageCombo1.List(i)
If AC.MatchCase Then
If Left$(ItemText, Len(AC.LastInput)) = AC.LastInput Then
Found = True
Exit For
End If
Else
If Left$(LCase$(ItemText), Len(AC.LastInput)) = LCase$(AC.LastInput) Then
Found = True
Exit For
End If
End If
Next i
' 如果找到匹配项,选中它
If Found Then
ImageCombo1.ListIndex = i
End If
End If
' 清除输入缓存
AC.LastInput = ""
End Sub
最佳实践
- 错误处理
vb
Private Function SafeAddItem(ByVal Text As String, _
ByVal ImageIndex As Long) As Boolean
On Error GoTo ErrorHandler
With ImageCombo1
.AddItem Text
.ListImages(.ListCount - 1).Picture = ImageIndex
End With
SafeAddItem = True
Exit Function
ErrorHandler:
Debug.Print "添加项目失败: " & Err.Description
SafeAddItem = False
End Function
- 数据导出导入
vb
Private Sub SaveItemsToFile(ByVal FilePath As String)
Dim FileNum As Long
FileNum = FreeFile
Open FilePath For Output As #FileNum
With ImageCombo1
Dim i As Long
For i = 0 To .ListCount - 1
Print #FileNum, .List(i) & "," & _
.ListImages(i).Picture & "," & _
.ItemData(i)
Next i
End With
Close #FileNum
End Sub
Private Sub LoadItemsFromFile(ByVal FilePath As String)
Dim FileNum As Long
FileNum = FreeFile
Open FilePath For Input As #FileNum
With ImageCombo1
' 清空现有项目
Do While .ListCount > 0
.RemoveItem 0
Loop
' 读取项目
Do While Not EOF(FileNum)
Dim Line As String
Line Input #FileNum, Line
Dim Parts() As String
Parts = Split(Line, ",")
If UBound(Parts) >= 2 Then
.AddItem Parts(0)
.ListImages(.ListCount - 1).Picture = CLng(Parts(1))
.ItemData(.ListCount - 1) = CLng(Parts(2))
End If
Loop
End With
Close #FileNum
End Sub
- 状态保存
vb
Private Sub SaveImageComboState()
SaveSetting App.Title, "ImageCombo", "SelectedIndex", CStr(ImageCombo1.ListIndex)
SaveSetting App.Title, "ImageCombo", "AutoComplete", CStr(AC.Enabled)
End Sub
Private Sub RestoreImageComboState()
With ImageCombo1
.ListIndex = CLng(GetSetting(App.Title, "ImageCombo", "SelectedIndex", "-1"))
End With
AC.Enabled = CBool(GetSetting(App.Title, "ImageCombo", "AutoComplete", "True"))
End Sub
ImageCombo 控件通过在列表项旁边显示图像,提供了更直观的选择界面。通过合理的扩展,可以实现树形菜单、数据绑定和自动完成等功能。上述示例展示了 ImageCombo 控件的多种用法,开发者可以根据具体需求选择合适的实现方式。