如何使自定义ComboBox(OwnerDrawFixed)看起来像标准ComboBox的3D? [英] How to make a custom ComboBox (OwnerDrawFixed) looks 3D like the standard ComboBox?

查看:365
本文介绍了如何使自定义ComboBox(OwnerDrawFixed)看起来像标准ComboBox的3D?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个自定义ComboBox,继承自Winforms的标准ComboBox。对于我的自定义ComboBox,我将 DrawMode 设置为 OwnerDrawFixed DropDownStyle DropDownList 。然后我写我自己的 OnDrawItem 方法。但我结束了这样:





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






更新1:ButtonRenderer



全部搜索后,我发现


I am making a custom ComboBox, inherited from Winforms' standard ComboBox. For my custom ComboBox, I set DrawMode to OwnerDrawFixed and DropDownStyle to DropDownList. Then I write my own OnDrawItem method. But I ended up like this:

How do I make my Custom ComboBox to look like the Standard one?


Update 1: ButtonRenderer

After searching all around, I found the ButtonRenderer class. It provides a DrawButton static/shared method which -- as the name implies -- draws the proper 3D button. I'm experimenting with it now.


Update 2: What overwrites my control?

I tried using the Graphics properties of various objects I can think of, but I always fail. Finally, I tried the Graphics of the form, and apparently something is overwriting my button.

Here's the code:

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

And here's the result:

Replacing Me.Parent.CreateGraphics with e.Graphics got me this:

And doing the above + replacing Me.ClientRectangle with e.Bounds got me this:

Can anyone point me whose Graphics I must use for the ButtonRenderer.DrawButton method?

PS: The bluish border is due to my using PushButtonState.Default instead of PushButtonState.Normal


I Found An Answer! (see below)

解决方案

I forgot where I found the answer... I'll edit this answer when I remember.

But apparently, I need to set the Systems.Windows.Forms.ControlStyles flags. Especially the ControlStyles.UserPaint flag.

So, my New() now looks like this:

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

And now I can hook into the OnPaint event:

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

Note: Yes, the _ButtonArea rectangle must be enlarged by 1 pixel to all directions (up, down, left, right), or else there will be a 1-pixel 'perimeter' around the ButtonRenderer that shows garbage. Made me crazy for awhile until I read that I must enlarge the Control's rect for ButtonRenderer.

这篇关于如何使自定义ComboBox(OwnerDrawFixed)看起来像标准ComboBox的3D?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆