Ownerdrawn ComboBox Example
A sample owner-drawn ComboBox
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;
// Draw the background of the item
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);
}
}
//Draw item text
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));
// Draw the focus rectangle if the mouse hovers over an item
if ((e.State & DrawItemState.Focus) == DrawItemState.Focus)
e.DrawFocusRectangle();
//Draw the border around the whole DropDown area
using (Pen borderPen = new Pen(DropDownBorderColor, 1))
{
Point start;
Point end;
if (e.Index == 0)
{
//Draw top border
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);
}
//Draw left border
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);
//Draw Right border
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)
{
//Draw bottom border
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
andState=ComboBoxEdit
- That is necessary if theComboBox
style isDropDownList
- Version 1.01 - Changed the testing of the
e.State
flag - Version 1.00 - Initial release