如何使自定义ComboBox(OwnerDrawFixed)看起来像标准的ComboBox 3D?

pep*_*uan 8 vb.net combobox custom-controls visual-studio-2010 ondrawitem

我正在制作一个自定义的ComboBox,继承自Winforms的标准ComboBox.对于我的自定义组合框,我定DrawModeOwnerDrawFixedDropDownStyleDropDownList.然后我写自己的OnDrawItem方法.但我这样结束了:

标准与自定义组合框

如何使我的自定义组合框看起来像标准组合?


更新1:ButtonRenderer

在四处搜索之后,我找到了这ButtonRenderer堂课.它提供了一个DrawButton静态/共享方法 - 顾名思义 - 绘制正确的3D按钮.我现在正在试验它.


更新2:什么覆盖了我的控件?

我尝试使用我能想到的各种对象的图形属性,但我总是失败.最后,我尝试了表单的图形,显然有些东西覆盖了我的按钮.

这是代码:

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
Run Code Online (Sandbox Code Playgroud)

这是结果:

覆盖ButtonRenderer

更换Me.Parent.CreateGraphicse.Graphics了我这一点:

剪裁的ButtonRenderer

而做上述+更换Me.ClientRectanglee.Bounds了我这一点:

收缩ButtonRenderer

任何人都可以指出我的方法必须使用哪些图形ButtonRenderer.DrawButton

PS:蓝色边框是由于我使用PushButtonState.Default而不是PushButtonState.Normal


我找到了答案!(见下文)

pep*_*uan 7

我忘记了找到答案的地方......当我记得的时候,我会编辑这个答案.

但显然,我需要设置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
Run Code Online (Sandbox Code Playgroud)

现在我可以加入这个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
Run Code Online (Sandbox Code Playgroud)

注意:是的,_ButtonArea矩形必须向所有方向(向上,向下,向左,向右)放大1个像素,否则ButtonRenderer周围将显示1个像素的"周长",显示垃圾.让我疯了一会儿,直到我读到我必须为ButtonRenderer放大Control的rect.