Overview
FontComboBox
is a ComboBox
derived class that has been
wrapped into a .NET
control library. It will drop down a list of all the true type fonts installed
on your machine. There are two styles for the FontComboBox
- one in which every font name is rendered
using it's font, and the other where every font name is shown using a default
font and then some text is shown using the selected font.
Using it in your project
Add the control to your toolbox
Right click on your toolbox and choose the Customize Toolbox option. Browse
to the FontCombo.dll file and add it to your toolbox.
Initialize the font combo-boxes
There is a public method named Populate
which you need to call on each of
your FontComboBox
objects.
public Form1()
{
InitializeComponent();
fontComboBox1.Populate(false);
fontComboBox2.Populate(true);
}
Retrieving the currently selected font
All you need to do is to use the Text
property.
private void button1_Click(object sender, System.EventArgs e)
{
textBox1.Font = new Font(fontComboBox1.Text,10);
textBox2.Font = new Font(fontComboBox2.Text,10);
}
Class reference
There is just one public method for you to use [other than any public methods
or properties available through the base classes]
Populate
public void Populate(bool b)
This will populate the combo box with all true type fonts that are installed
on your machine. The bool
parameter determines the style of
the combo box. Call Populate(false)
for a simple style font
combo box and call Populate(true)
for an elaborate style
font combo box. In simple style each font name is rendered using it's font. In
elaborate style, each font name is rendered using a default font, but some
sample text is rendered using the specific font.
Technical details
Basically this is an owner drawn combo box with the DrawMode
set to DrawMode.OwnerDrawVariable
. The first thing we need
to do would obviously be to enumerate the true type fonts on the machine. This
is done as follows [partial code snippet, refer source for complete code]
foreach (FontFamily ff in FontFamily.Families)
{
if(ff.IsStyleAvailable(FontStyle.Regular))
Items.Add(ff.Name);
}
Now we need to override OnMeasureItem
. This method is
called when an owner-drawn combo item needs to be drawn and is called before
OnDrawItem
. Here we can specify the width, height etc. We make use of
Graphics.MeasureString
to get the text extend of the rendered text in a
specific font.
protected override void OnMeasureItem(
MeasureItemEventArgs e)
{
...
Graphics g = CreateGraphics();
e.ItemHeight = (int)g.MeasureString(fontstring,
new Font(fontstring,10)).Height;
w = (int)g.MeasureString(fontstring,
new Font(fontstring,10)).Width;
if(both)
{
int h1 = (int)g.MeasureString(samplestr,
new Font(fontstring,10)).Height;
int h2 = (int)g.MeasureString(
Items[e.Index].ToString(),
new Font("Arial",10)).Height;
int w1 = (int)g.MeasureString(samplestr,
new Font(fontstring,10)).Width;
int w2 = (int)g.MeasureString(
Items[e.Index].ToString(),
new Font("Arial",10)).Width;
...
}
...
}
Now obviously we handle OnDrawItem
where we do our
actual drawing stuff.
protected override void OnDrawItem(
DrawItemEventArgs e)
{
...
string fontstring = Items[e.Index].ToString();
nfont = new Font(fontstring,10);
Font afont = new Font("Arial",10);
if(both)
{
Graphics g = CreateGraphics();
int w = (int)g.MeasureString(fontstring,
afont).Width;
if((e.State & DrawItemState.Focus)==0)
{
e.Graphics.FillRectangle(new SolidBrush(
SystemColors.Window),
e.Bounds.X+ttimg.Width,e.Bounds.Y,
e.Bounds.Width,e.Bounds.Height);
e.Graphics.DrawString(fontstring,afont,
new SolidBrush(SystemColors.WindowText),
e.Bounds.X+ttimg.Width*2,e.Bounds.Y);
e.Graphics.DrawString(samplestr,nfont,
new SolidBrush(SystemColors.WindowText),
e.Bounds.X+w+ttimg.Width*2,e.Bounds.Y);
}
else
{
...
}
}
else
{
if((e.State & DrawItemState.Focus)==0)
{
e.Graphics.FillRectangle(new SolidBrush(
SystemColors.Window),
e.Bounds.X+ttimg.Width,e.Bounds.Y,
e.Bounds.Width,e.Bounds.Height);
e.Graphics.DrawString(fontstring,nfont,
new SolidBrush(SystemColors.WindowText),
e.Bounds.X+ttimg.Width*2,e.Bounds.Y);
}
else
{
...
}
}
...
}
Acknowledgments
- Chris Losinger - I wrote this class partially due to my current
project's requirements and partially because I was inspired by Chris
Losinger's MFC font combo box.
- Senkwe Chanda - Senkwe's excellent beginner article for making
owner drawn combo boxes helped me a great deal.
- Nnamdi Onyeyiri - Nnamdi was with me on Sonork when I wrote this
class and I owe him the tip for using system font colors for highlighting .
Initially I was using a hard coded color.
Links