This tip shows how to change the look of the combobox dropdown list using ownerdrawn ComboBoxes.
Background
So there I was, rummaging around Q&A when I encountered OliveiraGui who had a question about how to change the look of the combobox
dropdown list (more specifically, the border color).
He had discovered that there were no properties to change that, and my reply to him was that it could be done, but that he had to ownerdraw the ComboBox
to do it, and I gave him a few examples of ownerdrawn combobox
es.
Painting your own ComboBox
is not really that hard, nor is it that complicated or requires a lot of code. The important part is knowing how to do it. It helps if you have meddled around with drawing in GDI+ or if you have done a fair amount of custom control development.
Afterwards, I thought about it, and I found the question interesting enough to do a small sample for him.
The thing is that even with owner-drawing, it's not really that easy to get access to the dropdown window itself. But it's quite easy to change the appearance of the individual items and thus mimic that the entire window has been changed.
So here is a ComboBox
where you can change the BorderColor
and BackColor
of the dropdown list. For demonstration purposes, I've made the default color values red and yellow. If you were to use this code in a real project, it would probably be a good idea to change that to black and white.
If you study the code, you will see that it is also very easy to change the appearance of the individual items in the dropdown list, e.g., the forecolor, font, etc. But I leave that up to you as a follow-up exercise.
The Code
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace OwnerDrawnComboBoxTest
{
[ToolboxBitmap(typeof(ComboBox))]
class ComboBoxEx : ComboBox
{
public ComboBoxEx()
{
this.DrawMode = DrawMode.OwnerDrawFixed;
this.DrawItem += ComboBoxEx_DrawItem;
this.DropDownBorderColor = Color.Red;
this.DropDownBackColor = Color.Yellow;
}
[Category("Appearance")]
[Description("The border color of the drop down list")]
[DefaultValue(typeof(Color), "Red")]
public Color DropDownBorderColor { get; set; }
[Category("Appearance")]
[Description("The background color of the drop down list")]
[DefaultValue(typeof(Color), "Yellow")]
public Color DropDownBackColor { get; set; }
private void ComboBoxEx_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0)
return;
if ((e.State & DrawItemState.ComboBoxEdit) == DrawItemState.ComboBoxEdit)
return;
if (
((e.State & DrawItemState.Focus) == DrawItemState.Focus) ||
((e.State & DrawItemState.Selected) == DrawItemState.Selected) ||
((e.State & DrawItemState.HotLight) == DrawItemState.HotLight)
)
{
e.DrawBackground();
}
else
{
using (Brush backgroundBrush = new SolidBrush(DropDownBackColor))
{
e.Graphics.FillRectangle(backgroundBrush, e.Bounds);
}
}
e.Graphics.DrawString(Items[e.Index].ToString(), this.Font, Brushes.Black,
new RectangleF(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height));
if ((e.State & DrawItemState.Focus) == DrawItemState.Focus)
e.DrawFocusRectangle();
using (Pen borderPen = new Pen(DropDownBorderColor, 1))
{
Point start;
Point end;
if (e.Index == 0)
{
start = new Point(e.Bounds.Left, e.Bounds.Top);
end = new Point(e.Bounds.Left + e.Bounds.Width - 1, e.Bounds.Top);
e.Graphics.DrawLine(borderPen, start, end);
}
start = new Point(e.Bounds.Left, e.Bounds.Top);
end = new Point(e.Bounds.Left, e.Bounds.Top + e.Bounds.Height - 1);
e.Graphics.DrawLine(borderPen, start, end);
start = new Point(e.Bounds.Left + e.Bounds.Width - 1, e.Bounds.Top);
end = new Point(e.Bounds.Left + e.Bounds.Width - 1,
e.Bounds.Top + e.Bounds.Height - 1);
e.Graphics.DrawLine(borderPen, start, end);
if (e.Index == Items.Count - 1)
{
start = new Point(e.Bounds.Left, e.Bounds.Top + e.Bounds.Height - 1);
end = new Point(e.Bounds.Left + e.Bounds.Width - 1,
e.Bounds.Top + e.Bounds.Height - 1);
e.Graphics.DrawLine(borderPen, start, end);
}
}
}
}
}
History
- Version 1.03 - Added Using
- Version 1.02 - Added check for
Index=-1
and State=ComboBoxEdit
- That is necessary if the ComboBox
style is DropDownList
- Version 1.01 - Changed the testing of the
e.State
flag - Version 1.00 - Initial release