Introduction
System painter is a little utility for viewing .NET framework system defined
hatches from System.Drawing.Drawing2D.HatchStyle
and windows system
colors and named colors from Color
structure.
The example shows how to use different brushes and how to extend
ListBox
with owner drawn code.
Painters
The code uses 2 different painters (with easy ability to create new different
ones). All painters implement IPainter
interface. All the interface
does it to get the name that will show in list box and Brush
used
for filling.
public interface IPainter
{
Brush PaintBrush
{
get;
}
string Name
{
get;
}
}
We also have utility enumeration for available painters:
public enum PaintType
{
Hatches,
SystemColors,
Colors
}
First painter is the color painter. All it does is filling the listbox item
with solid color:
public class ColorPainter : IPainter
{
Color color;
public ColorPainter(Color color)
{
this.color = color;
}
public string Name
{
get { return color.ToKnownColor().ToString(); }
}
public Brush PaintBrush
{
get { return new SolidBrush(color); }
}
}
And another one is Hatch
painter that uses hatch brush:
public class HatchPainter : IPainter
{
HatchStyle style;
Color color1;
Color color2;
public HatchPainter(HatchStyle style, Color color1, Color color2)
{
this.style = style;
this.color1 = color1;
this.color2 = color2;
}
public string Name
{
get { return style.ToString(); }
}
public Brush PaintBrush
{
get {
return new HatchBrush(style, color1, color2);
}
}
....
That's it for painters. We have 3 different types and only 2 painters because
SystemColor
s and Colors use the same painter.
ListBox
The implementation of the listbox is an owner drawn listbox. To do that all
we have to do is:
this.DrawMode = DrawMode.OwnerDrawFixed;
in constructor.
We also have custom
PaintType
property on the listbox that decides
what type of painter to use:
public PaintType PaintType
{
get { return this.paintType; }
set
{
paintType = value;
InitValues();
}
}
when we assign this property we initialize the items in the list:
void InitValues()
{
this.Items.Clear();
if (paintType == PaintType.Hatches)
{
foreach (HatchStyle style in Enum.GetValues(typeof(HatchStyle)))
{
IPainter painter = new HatchPainter(style,
Color.Blue, Color.Transparent);
Items.Add(painter);
}
}
else if (paintType == PaintType.Colors)
{
foreach (KnownColor kcolor in Enum.GetValues(typeof(KnownColor)))
{
Color color = Color.FromKnownColor(kcolor);
if (!color.IsSystemColor)
{
IPainter painter = new ColorPainter(color);
Items.Add(painter);
}
}
}
else if (paintType == PaintType.SystemColors)
{
foreach (KnownColor kcolor in Enum.GetValues(typeof(KnownColor)))
{
Color color = Color.FromKnownColor(kcolor);
if (color.IsSystemColor)
{
IPainter painter = new ColorPainter(color);
Items.Add(painter);
}
}
}
}
Depending on the type of painter that we want to use, we populate the list
with IPainter
values. Later when we draw the items we don't care
about what type of list it is, because IPainter
will tell us how to
paint it. And finally the draw item code:
IPainter painter = (IPainter)Items[e.Index];
Brush brush = painter.PaintBrush;
g.FillRectangle(brush, e.Bounds);
g.DrawLine(Pens.Black, e.Bounds.X, e.Bounds.Bottom-1,
e.Bounds.Right, e.Bounds.Bottom-1);
string name = painter.Name;
int width = (int)g.MeasureString(name, Font).Width;
g.FillRectangle((e.State & DrawItemState.Selected) ==
DrawItemState.Selected ? Brushes.Yellow : Brushes.White,
3, e.Bounds.Top+3, width+3, Font.Height+5);
g.DrawRectangle(Pens.Black, 3, e.Bounds.Top+3, width+3, Font.Height+5);
g.DrawString(painter.Name, Font, Brushes.Black, 5, e.Bounds.Top+5);
brush.Dispose();
We fill the area with painters brush, draw line below each item to separate
them, and draw a box with painters name.