我正在制作一个自定义的ComboBox,它继承自Winforms的标准ComboBox。对于我的自定义ComboBox,我将DrawMode
设置为OwnerDrawFixed
,并将DropDownStyle
设置为DropDownList
。然后,我编写自己的OnDrawItem
方法。但是我最终却是这样的:
如何使我的自定义组合框看起来像标准组合框?
更新1:ButtonRenderer
到处搜索后,我发现了 ButtonRenderer
class。它提供了DrawButton
静态/共享方法,顾名思义,该方法绘制了正确的3D按钮。我现在正在尝试。
更新2:什么覆盖了我的控件?
我尝试使用可以想到的各种对象的Graphics属性,但是我总是失败。最后,我尝试了表单的“图形”,显然是某些内容覆盖了我的按钮。
这是代码:
Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
Dim TextToDraw As String = _DefaultText
__Brush_Window.Color = Color.FromKnownColor(KnownColor.Window)
__Brush_Disabled.Color = Color.FromKnownColor(KnownColor.GrayText)
__Brush_Enabled.Color = Color.FromKnownColor(KnownColor.WindowText)
If e.Index >= 0 Then
TextToDraw = _DataSource.ItemText(e.Index)
End If
If TextToDraw.StartsWith("---") Then TextToDraw = StrDup(3, ChrW(&H2500)) ' U+2500 is "Box Drawing Light Horizontal"
If (e.State And DrawItemState.ComboBoxEdit) > 0 Then
'ButtonRenderer.DrawButton(e.Graphics, e.Bounds, VisualStyles.PushButtonState.Default)
Else
e.DrawBackground()
End If
With e
If _IsEnabled(.Index) Then
.Graphics.DrawString(TextToDraw, Me.Font, __Brush_Enabled, .Bounds.X, .Bounds.Y)
Else
'.Graphics.FillRectangle(__Brush_Window, .Bounds)
.Graphics.DrawString(TextToDraw, Me.Font, __Brush_Disabled, .Bounds.X, .Bounds.Y)
End If
End With
TextToDraw = Nothing
ButtonRenderer.DrawButton(Me.Parent.CreateGraphics, Me.ClientRectangle, VisualStyles.PushButtonState.Default)
'MyBase.OnDrawItem(e)
End Sub
结果如下:用
Me.Parent.CreateGraphics
替换e.Graphics
得到了这个:并执行以上操作,用
Me.ClientRectangle
替换e.Bounds
后,我得到了这一点:谁能指出我必须为
ButtonRenderer.DrawButton
方法使用的图形?PS:蓝色边框是由于我使用PushButtonState.Default而不是PushButtonState.Normal
我找到答案了! (见下文)
最佳答案
我忘记了找到答案的地方...当我记得时,我将编辑此答案。
但显然,我需要设置Systems.Windows.Forms.ControlStyles
标志。特别是ControlStyles.UserPaint
标志。
因此,我的New()
现在看起来像这样:
Private _ButtonArea as New Rectangle
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
MyBase.SetStyle(ControlStyles.Opaque Or ControlStyles.UserPaint, True)
MyBase.DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed
MyBase.DropDownStyle = ComboBoxStyle.DropDownList
' Cache the button's modified ClientRectangle (see Note)
With _ButtonArea
.X = Me.ClientRectangle.X - 1
.Y = Me.ClientRectangle.Y - 1
.Width = Me.ClientRectangle.Width + 2
.Height = Me.ClientRectangle.Height + 2
End With
End Sub
现在,我可以加入
OnPaint
事件:Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
If Me.DroppedDown Then
ButtonRenderer.DrawButton(Me.CreateGraphics, _ButtonArea, VisualStyles.PushButtonState.Pressed)
Else
ButtonRenderer.DrawButton(Me.CreateGraphics, _ButtonArea, VisualStyles.PushButtonState.Normal)
End If
MyBase.OnPaint(e)
End Sub
注意:是的,
_ButtonArea
矩形必须在所有方向(向上,向下,向左,向右)放大1个像素,否则ButtonRenderer周围将有一个1像素的“周长”,显示为垃圾。让我发疯了一段时间,直到我读了I must enlarge the Control's rect for ButtonRenderer.
关于vb.net - 如何使自定义ComboBox(OwnerDrawFixed)看起来像标准ComboBox的3D?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5864633/