当鼠标悬停在Listbox项目上时,突出显示该项目

3

我成功地通过ownerdrawn自定义了普通列表框中的图像、更改文本和背景颜色,当项目被选中时。现在我想实现的是:当鼠标悬停在列表框项目上时,在项目上绘制自定义的高亮颜色,这是否可能呢......下面是我的示例代码,展示了我目前已经做到的。

If e.Index = -1 Then Exit Sub
        Dim listBox As ListBox = CType(sender, ListBox)
        e.DrawBackground()
        Dim isItemSelected As Boolean = ((e.State And DrawItemState.Selected) = DrawItemState.Selected)
        If e.Index >= 0 AndAlso e.Index < listBox.Items.Count Then
            Dim textSize As SizeF = e.Graphics.MeasureString(listBox.Items(e.Index).ToString(), listBox.Font)
            Dim itemImage As Image = My.Resources.FolderHorizontal
            'set background and text color
            Dim backgroundColorBrush As New SolidBrush(If((isItemSelected), Color.CornflowerBlue, Color.White))
            Dim itemTextColorBrush As Color = If((isItemSelected), Color.White, Color.Black)

            e.Graphics.FillRectangle(backgroundColorBrush, e.Bounds)
            'draw the item image
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality
            e.Graphics.DrawImage(itemImage, e.Bounds.X + 2, _
                               e.Bounds.Y + (e.Bounds.Height - textSize.Height) / 2, _
                               itemImage.Width, itemImage.Height)
            'draw the item text
            Dim x, y As Single
            Dim h As Single = textSize.Height
            Dim rect As Rectangle = e.Bounds
            rect.X += listBox.ItemHeight
            rect.Width -= listBox.ItemHeight

            x = rect.X - 3
            y = rect.Y + (rect.Height - h) / 2

            Dim itemText As String = listBox.Items(e.Index).ToString()
            TextRenderer.DrawText(e.Graphics, itemText, e.Font, _
                                  New Rectangle(x, y, ClientRectangle.Width, ClientRectangle.Height), _
                                  itemTextColorBrush, TextFormatFlags.Default)
            'clean up
            backgroundColorBrush.Dispose()

        End If
        e.DrawFocusRectangle()
2个回答

2
您可以使用IndexFromPoint来实现这样的功能:
Dim mouseIndex As Integer = -1

Private Sub ListBox1_MouseMove(sender As Object, e As MouseEventArgs) _
                               Handles ListBox1.MouseMove
  Dim index As Integer = ListBox1.IndexFromPoint(e.Location)
  If index <> mouseIndex Then
    If mouseIndex > -1 Then
      Dim oldIndex As Integer = mouseIndex
      mouseIndex = -1
      If oldIndex <= ListBox1.Items.Count - 1 Then
        ListBox1.Invalidate(ListBox1.GetItemRectangle(oldIndex))
      End If
    End If
    mouseIndex = index
    If mouseIndex > -1 Then
      ListBox1.Invalidate(ListBox1.GetItemRectangle(mouseIndex))
    End If
  End If
End Sub

然后在您的绘图代码中:

If mouseIndex > -1 AndAlso mouseIndex = e.Index Then
  backgroundColorBrush = New SolidBrush(Color.DarkMagenta)
End If

谢谢,它可以工作...有一个小问题,如何减少闪烁,我认为每次鼠标移动到项目上时都会重新绘制,或者还有其他方法可以做到...但除此之外,它运行得很好。 - mercenary
@mercenary ListBox控件有点闪烁过度,但我更新了帖子以减少一些。考虑改用ListView控件。 - LarsTech
谢谢,我在考虑使用ListView,也许在工具的下一个版本中会使用它。这是一个文件夹图标更改器,使用ListBox来容纳多个文件夹。 - mercenary

1
我将向您展示如何完成这个任务。所有专家都表示这很复杂,使用列表框无法完成...但我能在5分钟内完成。
我创建的列表框名称为listPOSSIBILITIES
1)创建一个全局变量并放置在您的表单中。
Dim HOVERTIME As Boolean = True

2) 创建 MouseEnter 事件

Private Sub listPOSSIBILITIES_MouseEnter(sender As Object, e As system.EventArgs) Handles listPOSSIBILITIES.MouseEnter

    HOVERTIME = True

End Sub

创建 MouseLeave 事件。
Private Sub listPOSSIBILITIES_MouseLeave(sender As Object, e As System.EventArgs) Handles listPOSSIBILITIES.MouseLeave

    HOVERTIME = False

End Sub

创建 MouseMove 事件。
Private Sub listPOSSIBILITIES_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles listPOSSIBILITIES.MouseMove

    Dim mypoint As Point
    mypoint = listPOSSIBILITIES.PointToClient(Cursor.Position)
    Dim myindex As Integer = listPOSSIBILITIES.IndexFromPoint(mypoint)
    If myindex < 0 Then Exit Sub
    listPOSSIBILITIES.SelectedIndex = myindex

End Sub

创建MouseClick事件。
Private Sub listPOSSIBILITIES_MouseClick(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles listPOSSIBILITIES.MouseClick

    HOVERTIME = False

End Sub

6) 创建SelectedIndexChanged事件

Private Sub listPOSSIBILITIES_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles listPOSSIBILITIES.SelectedIndexChanged

    If HOVERTIME Then Exit Sub

    'put the rest of your code after this above If statement

End Sub

这是因为MouseClick事件在SelectIndexChanged事件之前被触发。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接