Reputation: 619
I changed the highlight color of various of the controls, and I am planning to make more changes. So I though is better to create my own controls and reuse them instead of making the changed for each and every one of them.
I created a new user control, and inherited from System.Windows.Forms.ComboBox
.
The problem is I cannot find a way to override onDraw
like I would for onClick
.
So how I would go and override it? Here is the code I used for each control onDraw
event
public void comboMasterUsers_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
Graphics g = e.Graphics;
Brush brush = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ?
Brushes.LightSeaGreen : new SolidBrush(e.BackColor);
g.FillRectangle(brush, e.Bounds);
e.Graphics.DrawString(comboMasterUsers.Items[e.Index].ToString(), e.Font,
new SolidBrush(e.ForeColor), e.Bounds, StringFormat.GenericDefault);
e.DrawFocusRectangle();
}
Thanks!
Upvotes: 2
Views: 13129
Reputation: 26
It will useful for someone who looking for VB.net
Public Class myCombo
Inherits ComboBox
Public Property SelectedBackColor As Color
Public Sub New()
AddHandler DrawItem, New DrawItemEventHandler(AddressOf DrawCustomMenuItem)
DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed
DropDownStyle = ComboBoxStyle.DropDownList
End Sub
Protected Sub DrawCustomMenuItem(ByVal sender As Object, ByVal e As DrawItemEventArgs)
If e.Index < 0 Then
Return
End If
e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
Dim Cb As ComboBox = TryCast(sender, ComboBox)
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
e.Graphics.FillRectangle(New SolidBrush(Color.OrangeRed), e.Bounds) ' selected item background color
Else
e.Graphics.FillRectangle(New SolidBrush(Color.White), e.Bounds) ' background color
End If
e.Graphics.DrawString(Cb.Items(e.Index).ToString(), e.Font, New SolidBrush(e.ForeColor),
New Point(e.Bounds.X, e.Bounds.Y), StringFormat.GenericTypographic)
End Sub
End Class
Upvotes: 0
Reputation: 54433
Here you go:
public class myCombo : ComboBox
{
// expose properties as needed
public Color SelectedBackColor{ get; set; }
// constructor
public myCombo()
{
DrawItem += new DrawItemEventHandler(DrawCustomMenuItem);
DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
SelectedBackColor= Color.LightSeaGreen;
}
protected void DrawCustomMenuItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
// a dropdownlist may initially have no item selected, so skip the highlighting:
if (e.Index >= 0)
{
Graphics g = e.Graphics;
Brush brush = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ?
new SolidBrush(SelectedBackColor) : new SolidBrush(e.BackColor);
Brush tBrush = new SolidBrush(e.ForeColor);
g.FillRectangle(brush, e.Bounds);
e.Graphics.DrawString(this.Items[e.Index].ToString(), e.Font,
tBrush, e.Bounds, StringFormat.GenericDefault);
brush.Dispose();
tBrush.Dispose();
}
e.DrawFocusRectangle();
}
}
You may consider exposing more Properties as you expand your customziation, so you can change them for each instance when you want to..
Also don't forget to dispose GDI objects you create, like brushes and pens!
Edit: Just noticed that BackColor
would hide the original property. Changed it to SelectedBackColor
, which actually says what it is!
Edit 2: As Simon noted in the comments, there is a HasFlag
method and so as of .Net 4.0 one can also write:
Brush brush = ((e.State.HasFlag(DrawItemState.Selected) ?
which is a little clearer and shorter.
Edit 3: Actually for drawing onto controls the use of TextRenderer.DrawText
is recommended over graphics.DrawString
..
Upvotes: 10
Reputation: 41
Thanks for this helpful post. I made one small enhancement that others may find useful.
When the ComboBox has its DisplayMember property set to access a specific property of the displayed items, ToString() may not give the expected text. The fix for this is to use:
GetItemText(Items[e.Index])
to retrieve the required text in the call to DrawString().
Upvotes: 1