winforms 是否有方法将可单击的图标添加到ComboBox?

vm0i2vca  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(167)

我目前正在www.example.com上开发一个WinForms应用程序vb.net,在那里你可以在一个组合框中选择不同的数据。这些组合框中的项目可以编辑或删除,所以我的问题是:是否有办法为每个项目添加图标(例如铅笔和垃圾桶),以向用户显示“单击此处编辑”或“单击此处删除”?
在我的脑海里,它看起来像下面的图片:

非常感谢你的评分

ee7vknir

ee7vknir1#

我通过从ComboBox继承类创建了一个新的组合框控件。

Imports System.ComponentModel

Public Class ComboBoxEx
    Inherits ComboBox

    ...
End Class

我们的想法是使用DrawModeDrawMode.OwnerDrawFixed,并在代码中完成所有的绘制。这允许我们绘制代表可点击按钮的图像。我添加了两个图像作为项目的资源(My.Resources.pencilMy.Resources.Trash_16x16,您的可能有不同的名称)。

Const IconSize = 20

Dim stringFormat As StringFormat = New StringFormat() With {.LineAlignment = StringAlignment.Center}

Public Sub New()
    DrawMode = DrawMode.OwnerDrawFixed
    DropDownStyle = ComboBoxStyle.DropDownList
    ItemHeight = 21
End Sub

Protected Overrides Sub OnDrawItem(e As DrawItemEventArgs)
    e.DrawBackground()

    If e.Index >= 0 Then
        Dim g As Graphics = e.Graphics
        Dim brushColor = If(((e.State And DrawItemState.Selected) <> 0),
            SystemColors.Highlight,
            e.BackColor)
        Using brush As Brush = New SolidBrush(brushColor)
            g.FillRectangle(brush, e.Bounds)
        End Using
        Using textBrush As Brush = New SolidBrush(e.ForeColor)
            g.DrawString(Items(e.Index).ToString(), e.Font, textBrush, e.Bounds, stringFormat)
        End Using

        ' Skip the default item at index = 0 and the text box area (DrawItemState.ComboBoxEdit)
        If e.Index > 0 And (e.State And DrawItemState.ComboBoxEdit) = 0 Then
            Dim image = My.Resources.pencil
            Dim point = New Point(
                Width - 2 * IconSize + (IconSize - image.Width) \ 2,
                e.Bounds.Y + (ItemHeight - image.Height) \ 2)
            g.DrawImage(image, point)

            image = My.Resources.Trash_16x16
            point = New Point(
                Width - IconSize + (IconSize - image.Width) \ 2,
                e.Bounds.Y + (ItemHeight - image.Height) \ 2)
            g.DrawImage(image, point)
        End If
    End If

    e.DrawFocusRectangle()
End Sub

这是可视部分。现在我们必须检测鼠标在下拉列表中的按钮上的点击,并在点击时引发事件。

Dim isDroppedDown As Boolean

Public Event Button1Clicked()
Public Event Button2Clicked()

Protected Overrides Sub OnDropDown(e As EventArgs)
    isDroppedDown = True
    MyBase.OnDropDown(e)
End Sub

Protected Overrides Sub OnDropDownClosed(e As EventArgs)
    isDroppedDown = False
    MyBase.OnDropDownClosed(e)
End Sub

Protected Overrides Sub WndProc(ByRef m As Message)
    Const WM_COMMAND = &H111

    If LicenseManager.UsageMode = LicenseUsageMode.Runtime And isDroppedDown And
        m.Msg = WM_COMMAND And (CType(m.WParam, Int64) >> 16) = 1 Then

        Dim button = ButtonClicked()
        ' If the user clicked a button (skipping default item)
        If button <> 0 And SelectedIndex > 0 Then
            m.Result = New IntPtr(1)
            If button = 1 Then
                RaiseEvent Button1Clicked()
            Else
                RaiseEvent Button2Clicked()
            End If
            Return
        End If
    End If
    MyBase.WndProc(m)
End Sub

Private Function ButtonClicked() As Integer
    Dim pos = PointToClient(MousePosition)

    If pos.X > Size.Width - IconSize Then
        Return 2
    ElseIf pos.X > Size.Width - 2 * IconSize Then
        Return 1
    End If
    Return 0
End Function

编译项目后,这个新的ComboBoxEx会出现在winforms工具箱中,您可以将它拖放到窗体中。
然后,您可以在窗体中处理按钮事件

Private Sub ComboBoxEx1_Button1Clicked() Handles ComboBoxEx1.Button1Clicked
    Label1.Text = $"Pen clicked. Item = {ComboBoxEx1.SelectedItem.ToString()}"
End Sub

Private Sub ComboBoxEx1_Button2Clicked() Handles ComboBoxEx1.Button2Clicked
    Label1.Text = $"Trash bin clicked. Item = {ComboBoxEx1.SelectedItem.ToString()}"
End Sub

您可能需要调整图标大小、文本大小等来满足您的需要。

相关问题