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
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
1条答案
按热度按时间ee7vknir1#
我通过从
ComboBox
继承类创建了一个新的组合框控件。我们的想法是使用
DrawMode
DrawMode.OwnerDrawFixed
,并在代码中完成所有的绘制。这允许我们绘制代表可点击按钮的图像。我添加了两个图像作为项目的资源(My.Resources.pencil
和My.Resources.Trash_16x16
,您的可能有不同的名称)。这是可视部分。现在我们必须检测鼠标在下拉列表中的按钮上的点击,并在点击时引发事件。
编译项目后,这个新的
ComboBoxEx
会出现在winforms工具箱中,您可以将它拖放到窗体中。然后,您可以在窗体中处理按钮事件
您可能需要调整图标大小、文本大小等来满足您的需要。