In this short article, I am trying to create a ColorComboBox control which allows the user to select colors from System.Drawing.Color struct. From Mahesh Chand's color code snippet, I was inspired by the idea of listing color using reflection. So I thought it would be good if we can convert the code into a control.
Snapshot
The end control is shown in the snap shot below:
Steps involved in creating Control
The article is subdivided into creation of the custom combobox class and implementation of the draw events.
Part 1: Create Custom ColorComboBox
For this, we have to create a new class and change the base class to ComboBox.
public class ColorComboBox : ComboBox
Part 2: Modify the constructor
We need to modify the constructor to fill the ComboBox with colors and change the draw mode.
public ColorComboBox()
{
FillColors();
// Change DrawMode for custom drawing
this.DrawMode = DrawMode.OwnerDrawFixed;
this.DropDownStyle = ComboBoxStyle.DropDownList;
}
Part 3: Implement the FillColors() method
For loading the combobox with color items, we need to use .Net Reflection. Following is the code to get all Color properties from struct Color.
private void FillColors()
{
this.Items.Clear();
// Fill Colors using Reflection
foreach (Color color in typeof(Color).GetProperties(BindingFlags.Static | BindingFlags.Public).Where(c => c.PropertyType == typeof(Color)).Select(c => (Color)c.GetValue(c, null)))
{
this.Items.Add(color);
}
}
For reduction of code I have used Lambda Expressions. Basically the code will iterate through all the properties which are static and public, then the Where() method will filter them by type of Color. The Select() method converts the PropetyInfo to Color object using c.GetValue() method.
Part 4: Custom Draw the control
Now we have the entire color items in the list. The next challenge is to display the item with the actual color filled in a rectangle and showing the color name next to it.
For this we have to override the OnDrawItem method of combobox.
protected override void OnDrawItem(DrawItemEventArgs e)
{
if (e.Index >= 0)
{
Color color = (Color)this.Items[e.Index];
int nextX = 0;
e.Graphics.FillRectangle(new SolidBrush(e.BackColor), e.Bounds);
DrawColor(e, color, ref nextX);
DrawText(e, color, nextX);
}
else
base.OnDrawItem(e);
}
Whenever the ComboBox item is painted the above OnDrawItem() method will be called. We basically check
whether the e.Index >= 0 to ensure there is a valid item in the list and do the custom drawing.
The drawing is divided into 3 steps.
- Paint the Background
- Draw the Color
- Draw the Text (color name)
Part 5: Add Property to get selected color
Now we need to add a new property to get/set the selected color.
public Color Color
{
get
{
if (this.SelectedItem != null)
return (Color)this.SelectedItem;
return Color.Black;
}
set
{
int ix = this.Items.IndexOf(value);
if (ix >= 0)
this.SelectedIndex = ix;
}
}
The above get code will return the selected color by converting selected item into Color struct.
The set code will allow us to set the selected color by taking the set value and iterating through the items in the combobox.
Using the Code
The attachment contains the ColorComboBox as well as the test form. For reusing the control, one may take the ColorComboBox file alone for integration into other projects.