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.

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

publicvoid 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]

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.

Share

About the Author

Nish is a real nice guy who has been writing code since 1990 when he first got his hands on an 8088 with 640 KB RAM. Originally from sunny Trivandrum in India, he has been living in various places over the past few years and often thinks it’s time he settled down somewhere.

Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com.

Comments and Discussions

My only issue is a total lack of memory management. The control is creating lots of disposable objects, and none of them ever get disposed. Graphics are not disposed in the draw method, fonts are created left and right, none of which are properly disposed when done.

Also, instead of creating brushes like this:

new SolidBrush(SystemColors.WindowText)

It is more efficient to simply use the system brushes in the framework:

SystemBrushes.WindowText

Aside from these issues, this is a very nice control, and one I spent a while looking for. Once again, thank you.

First of all big big thanks for the article, and the code you supplied.
It was my first time I truly understood the "OwnerDraw" hook, and I think it is the first time I used it correctly.

The changes I introduce are part performance, but also a lot of visual cleaning up and code cleanup that I felt was missed, also made the control a bit more generalized for usage from the Visual Form Designer.
List of changes:
- ComboBox and ToolStripComboBox "flavors:
- Sample text is user customized (also from Visual Designer)
- Font Size of sample is based on control font size
- Fonts are refreshed upon style changes
- all changes are synced, so are "more thread safe".
- Sample text (when used) is displayed on the far side of the list, giving a "cleaner" preview.
- Selected font, does not display Sample Text.
- hope I didn't miss anything....

I'd appreciate a thanks reply if someone finds it useful.
I would very much like a reply from the original poster.

When the items are indexed from zero then the items.count is NOT the last item. For example if you have five items, indexed as 0, 1, 2, 3 and 4 then you see that although the count is 5, the index of the last item is count-1.

Life in the fast lane is only fun if you live in a country with no speed limits.

Since a ComboBox AutoScales (ie, if you change the font size, the size of the control changes ),
you would probably want to make a change to your DrawItem method, and the MeasureItem method.
Instead of creating the default fon as a 10pt Arial, why not incorporate the Font property already
included in the ComboBox.

I made changes to that calls to measure string are only made if the sring really needs to be created.
Make a member for the arial font used to display the name + example.
Made the size of the fonts use a constant.
Made the sample text constant.
Made it so that the both had a meaningful name to me since I could not tell without looking at the code.
Made it so it only created the font a single time as opposed to all the calls to create temporary fonts in the calls.
Changed the spacing for the sample after the font name to be next to the font. It was using X+Width*2 changed it to X*2+Width.

Oh I also removed the bitmap since in my usage it was just more noise that I did not really want.

Thanks for the example, it did pretty much everything I needed.

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

There is a problem in my owner draw combo. I download yours and found the same problem. It is:
Scroll down your combo by the mouse wheel(ofcourse after drop down), you will find the items in it looked scroll incorrect.

I trace it found that the message about the index seemed not suitable.
Is it a bug of the ComboBox?
Do you have some opinion on this?

I found this artical amazing . But I missed the posibility of typing a part of a fontname and go directly to it. So I made some modifications. What I still plan to do with this control (when I have some more time) is add a history in the beginning of the list. Like Word it will first repeat the 5 recently used and draw a double line under it.