Introduction
The control is very simple but I think it is helpful for beginners in C# programming, especially .NET UserControl programming.
Behaviors
Just like Paintbrush color picker, our color picker must have the following features:
- An area which shows the current selected brush and pen color.
- Provides some predefined colors which is divided into two rows. The first row is darker than the second row.
- User would use the left mouse button to select pen color and right mouse button for brush color.
- When the user double clicks on a specified color cell, the application would ask the user which color they want to use by using the standard color picker dialog.
- And the last one, this control should have an event for notifying parent about the changing of brush and pen color.
Implement
First, we should create a new user control which contains several labels as Color Cell that you will see when you view the control in design time. After that, we should have a way to store the predefined colors and the selected brush and pen color. The example given below explains in detail how this can be done:
private const int TotalColors = 16;
private Color[] _Colors = new Color[TotalColors];
private int _selPenColor = 0;
private int _selBrushColor = 1;
public Color PenColor
{
get { return this._Colors[_selPenColor];}
set
{
this._Colors[0] = value;
this._selPenColor = 0;
}
}
public Color BrushColor
{
get {return this._Colors[_selBrushColor];}
set
{
this._Colors[TotalColors/2] = value;
this._selBrushColor = TotalColors/2;
}
}
In the next step, we should have some functions that should take care of drawing:
private void DrawSelectedColor(Graphics graph, Rectangle rect,
Color clrPen, Color clrBrush)
{
Brush brushBackground = new SolidBrush(this.BackColor);
Brush penBrush = new SolidBrush(clrPen);
Brush brushBrush = new SolidBrush(clrBrush);
Point ptCenter = new Point(rect.Left + rect.Width/2,
rect.Top + rect.Height/2);
int cellWidth = 16;
int cellHeight = 16;
int XMargin = 4;
int YMargin = 4;
Rectangle rectPen = new Rectangle(XMargin, YMargin,
cellWidth, cellHeight);
Rectangle rectBrush = new Rectangle(rect.Right-XMargin-cellWidth,
rect.Bottom-YMargin-cellHeight, cellWidth, cellHeight);
graph.FillRectangle(brushBackground, rect);
graph.FillRectangle(brushBrush, rectBrush);
ControlPaint.DrawBorder3D(graph, rectBrush, Border3DStyle.Raised);
graph.FillRectangle(penBrush, rectPen);
ControlPaint.DrawBorder3D(graph, rectPen, Border3DStyle.Raised);
ControlPaint.DrawBorder3D(graph, rect, Border3DStyle.Sunken);
penBrush.Dispose();
brushBrush.Dispose();
brushBackground.Dispose();
}
private void DrawColor(Graphics graph, Rectangle rect, Color color)
{
Brush brush = new SolidBrush(color);
graph.FillRectangle(brush, rect);
ControlPaint.DrawBorder3D(graph, rect, Border3DStyle.SunkenOuter);
brush.Dispose();
}
And just attach the implemented function to the standard drawing routing of the owner:
private void ColorButton_Paint(object sender, PaintEventArgs e)
{
if (sender is Label)
{
Label btn = sender as Label;
int colorID = Int32.Parse(btn.Tag.ToString());
DrawColor(e.Graphics, btn.DisplayRectangle, this._Colors[colorID]);
}
}
private void SelectColorButton_Paint(object sender, PaintEventArgs e)
{
DrawSelectedColor(e.Graphics, btnSelectedColors.DisplayRectangle,
this.PenColor, this.BrushColor);
}
As I mentioned before, we should have a delegate to notify the container about the changing of selected pen and brush color.
public event EventHandler PenColorChanged = null;
public event EventHandler BrushColorChanged = null;
...........
private void OnSelectedBrushColorChanged()
{
if (this.BrushColorChanged != null)
this.BrushColorChanged(this, new System.EventArgs());
}
private void OnSelectedPenColorChanged()
{
if (this.PenColorChanged != null)
this.PenColorChanged(this, new System.EventArgs());
}
And the last one, we should handle the selecting operation of end user:
private void ColorButton_MouseDown(object sender, MouseEventArgs e)
{
if (!(sender is Label)) return;
Label btn = sender as Label;
int colorID = Int32.Parse(btn.Tag.ToString());
if (e.Button == MouseButtons.Left)
this.SelectPenColorID = colorID;
else if (e.Button == MouseButtons.Right)
this.SelectedBrushColorID = colorID;
btnSelectedColors.Invalidate();
}
private void ColorButton_DoubleClick(object sender, System.EventArgs e)
{
if (!(sender is Label)) return;
Label btn = sender as Label;
int colorID = Int32.Parse(btn.Tag.ToString());
ColorDialog dlg = new ColorDialog();
dlg.Color = this._Colors[colorID];
dlg.FullOpen = false;
dlg.SolidColorOnly = true;
if (dlg.ShowDialog(this) == DialogResult.OK)
{
this._Colors[colorID] = dlg.Color;
this.Refresh();
}
}
And now, you can build your project and test your new Paintbrush - like Color Picker.