Introduction
If you search for Color Picker in CodeProject, you will easily get more than one dozen of them. The one I wanted was a color picker of combo box. There are already a few in CodeProject. However, I am not going to develop a derived class of ComboBox
, instead, I would use the design pattern introduced in this series of articles. You may compare this implementation with others.
Using the Code
The code was constructed with Visual Studio 2005, and it shouldn't be difficult to copy the code to other C# development environments.
public class ColorComboAgent
{
private ComboBox box;
private Color[] colorArray;
private Color currentColor;
private bool useCustomColor;
private bool SelectedIndexChangedEventEnabled;
public ColorComboAgent(ComboBox comboBox)
{
ColorConverter cc = new ColorConverter();
ICollection colorCollection = cc.GetStandardValues();
colorArray = new Color[colorCollection.Count + 1];
colorArray[0] = Color.White;
colorCollection.CopyTo(colorArray, 1);
InitializeList(comboBox);
SelectedIndexChangedEventEnabled = true;
}
private void InitializeList(ComboBox comboBox)
{
this.box = comboBox;
box.DropDownStyle = ComboBoxStyle.DropDownList;
box.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
box.DrawItem += new DrawItemEventHandler(DrawItemHandler);
box.SelectedIndexChanged += new EventHandler(box_SelectedIndexChanged);
LoadColorsToBox();
}
private void LoadColorsToBox()
{
if (box.Items.Count < 2)
box.DataSource = colorArray;
}
private void box_SelectedIndexChanged(object sender, EventArgs e)
{
if (!SelectedIndexChangedEventEnabled)
return;
if (box.SelectedIndex > 0)
currentColor = colorArray[box.SelectedIndex];
else
{
using (ColorDialog fm = new ColorDialog())
{
fm.Color = Color;
if (fm.ShowDialog() == DialogResult.OK)
Color = fm.Color;
}
}
}
public Color Color
{
get { return currentColor; }
set
{
int dx = -1;
currentColor = value;
for (int i = 0; i < colorArray.Length; i++)
{
if (colorArray[i] == value)
{
dx = i;
break;
}
}
useCustomColor = dx == -1;
if (useCustomColor)
{
colorArray[0] = currentColor;
dx = 0;
}
SelectedIndexChangedEventEnabled = false;
box.SelectedIndex = dx;
SelectedIndexChangedEventEnabled = true;
box.Refresh();
}
}
private void DrawItemHandler(object sender,
System.Windows.Forms.DrawItemEventArgs e)
{
e.DrawBackground();
Rectangle colorRectangle = new Rectangle(2, e.Bounds.Top + 1,
e.Bounds.Height * 2, e.Bounds.Height - 2);
e.Graphics.FillRectangle(new SolidBrush(colorArray[e.Index]),
colorRectangle);
if (e.Index > 0)
{
e.Graphics.DrawString(colorArray[e.Index].Name,
box.Font, System.Drawing.Brushes.Black,
new RectangleF(e.Bounds.X + colorRectangle.Width,
e.Bounds.Y, e.Bounds.Width, e.Bounds.Height));
}
else
{
if (useCustomColor)
e.Graphics.DrawString("Custom", box.Font,
System.Drawing.Brushes.Black,
new RectangleF(e.Bounds.X + colorRectangle.Width,
e.Bounds.Y, e.Bounds.Width, e.Bounds.Height));
else
e.Graphics.DrawString("Custom...", box.Font,
System.Drawing.Brushes.Black,
new RectangleF(e.Bounds.X + 2, e.Bounds.Y,
e.Bounds.Width, e.Bounds.Height));
}
}
}
In the client code of a Form, you may change the properties through the agent.
colorComboAgent agent = new ColorComboAgent(comboBox1))
agent.Color = Color.Red;
Color buttonColor = agent.Color;
Unlike in InTextboxLabel
which provides only visual effects, you will need to access ColorComboAgent
to access data, so you need to keep an explicit reference in the client code.
Points of Interest
In the first 2 articles of this series, I asked a question as to what this design pattern is, as I could not exactly map the common things of these examples with a particular pattern described in "Design Patterns - Elements of Reusable Object Oriented Software" by GOF. Reminded by one of the readers of these articles, I agreed that the design pattern is more like the Decorator Pattern rather than the Builder Pattern.
I would try to illustrate common things of these examples in the next article, to discuss whether it is worthy of giving it a distinguishing name of design pattern.
References
I started my IT career in programming on different embedded devices since 1992, such as credit card readers, smart card readers and Palm Pilot.
Since 2000, I have mostly been developing business applications on Windows platforms while also developing some tools for myself and developers around the world, so we developers could focus more on delivering business values rather than repetitive tasks of handling technical details.
Beside technical works, I enjoy reading literatures, playing balls, cooking and gardening.