Fonts define the symbols and characters used to display text in a Windows
program. In this section, you will learn
The basic attributes that are available for fonts
How to use the Common Font dialog box provided as part of Windows
MFC class library support for creating and managing fonts
At the end of the section is some sample code that extends the DCTest example
to show how fonts are used in a Windows program.
What Are Fonts?
Fonts are GDI objects, much like the pens and brushes discussed in Section
12, "Using Pens and Brushes," and are used to define the characters used
for output in a Windows program. A collection of characters and other symbols
that share the same attributes is a font.
Just a Minute: Strictly
speaking, fonts are not necessary for most programs written for Windows.
A default font is selected into every device context automatically, and
it can work just fine for most applications. However, almost every program
can benefit from using fonts that have been selected to suit its specific
needs.
In this section you see some terms that are unique to programming with
fonts.
New Term: A glyph is an individual
character.
New Term: Font pitch refers
to the width of individual characters; fixed pitch means that each
character has the same width; variable pitch means that some characters
will be wider than others.
New Term: A serif is the
small cross at the ends of some characters. A font with a serif has short
crosses at the ends of lines making up the font; Times New Roman is such
a serif font. A font without serifs is often called a sans-serif
font. Figure 13.1 shows examples of a serif and a sans-serif font.
Figure 13.1
Serif and sans-serif fonts.
Fonts are maintained by Windows. Information about each currently installed
font is stored in a system table known as the font table.
There are three different types of fonts; each type has different capabilities:
Raster fonts are created from bitmaps and are stored in resource
files with an .FON extension. Each bitmap is created for a specific
screen resolution and is used by Windows to map out exactly how the glyph
will look when it is displayed.
Vector fonts consist of a series of endpoints that are connected
together to create each glyph and also are found in files with an .FON
extension. Unlike raster fonts, vector fonts are device independent, but
they are the slowest of the three font types.
TrueTypefonts are the most flexible of all Windows fonts.
First introduced in Windows 3.1, TrueType fonts consist of line and curve
information, as well as hints about each glyph. Each TrueType font is stored
in two files: one with an .FOT extension, the other with a .TTF
extension.
Just a Minute: Scaleable
fonts that can display italic, bold, or underlined text give a program
an extra amount of usability. Most printers supported by Windows also allow
TrueType fonts to be displayed on a printer exactly as they are on a video
screen; this is an extra advantage because it greatly simplifies the work
required for printing.
Fonts are also arranged into six families that define the general attributes
of the font. Fonts in the same family share similar strokes, serifs, and
pitch. The following are the six font families:
Decorative specifies novelty fonts such as Old English.
Dontcare specifies a generic group of fonts; either the font family
information doesn't exist or the font family is unimportant.
Modern specifies fonts that have fixed pitch and may or may not
have serifs. Courier New is an example of a Modern font.
Roman specifies fonts that have variable pitch and have serifs,
such as Times New Roman.
Script specifies fonts that are similar to handwriting.
Swiss specifies a font that is fixed pitch and doesn't have serifs,
such as Arial.
Specifying Font Attributes
Like other GDI objects, the easiest way to use a font is to use the MFC
class library. Like other GDI objects, fonts must be used with a device
context, and they are influenced by the current state of the device context,
such as mapping mode and color definitions. When you're working with text
output, the CFont class helps make using a font easy.
There are two basic ways to use a font in your program:
You can specify exactly what kind of font should be used.
You can specify font general attributes and let Windows select a font for
you.
In addition to the font families discussed earlier in this section, you
can use other general attributes to specify a font. Many font attributes
exist, mainly because there are so many different ways to display characters
in a program written for Windows. Don't worry; after you've used fonts
a few times, you'll be able to create fonts with no trouble at all. Later
in the section you will build some examples to learn how you can use these
attributes.
The Font Height and Width
You can specify the height of the font using one of the following methods:
If a height greater than zero is specified, Windows tries to match the
requested height with one of the available fonts, and the font is mapped
using logical units.
If a font height of zero is specified, a reasonable default font is used.
In this case, "reasonable" is defined by Windows.
If the specified height is a negative number, the font is mapped using
hardware units. Windows searches for a font that matches the absolute value
of the size provided.
Logical units normally are used for screen display, and physical units
are normally used for printing. In Section 21, "Printing," you use MM_TWIPS
to create fonts based on device units.
Just a Minute: The width
of a font normally is set to zero, which tells Windows to select an appropriate
default width. However, in some cases you might want to specify your own
font width to display compressed or elongated text.
The Font Character Set
Every font is made up of a large number of characters and other symbols
that can be displayed. The actual symbols that are contained in a font
depend on the character set supported by that font. These three character
sets are available:
ANSI_CHARSET: Used for most output when programming in Windows.
This is the character set you're most likely to use. The symbol ANSI_CHARSET
is defined as equal to zero, which makes it easy to use as a default parameter.
OEM_CHARSET: Used mainly for console-mode programs; it is almost
identical to the ANSI character set. This character set is system dependent
and can't be used reliably for every machine capable of running Windows.
Some of the low- and high-numbered characters are different, but these
are rarely used in Windows.
SYMBOL_CHARSET: Used to display symbols such as the ones used
in math formulas.
Attributes that Affect Font Output
Three parameters specify output attributes of the selected font: output
precision, clipping precision, and output quality.
Output precision is used to specify how closely the font returned by
Windows must match the requested font. A range of options is available,
from allowing Windows to select a reasonable match to requiring an exact
match.
OUT_DEFAULT_PRECIS: Used when Windows can choose a "reasonable"
font. This is the option selected most often and is equivalent to using
zero as a parameter.
OUT_STRING_PRECIS: Used to specify that the font chosen by Windows
must match the requested font's size.
OUT_CHARACTER_PRECIS: Used to specify that the font must match
all requested attributes except orientation and escapement, which are defined
later in the section "Other Font Attributes."
OUT_STROKE_PRECIS: Used to specify that the font chosen must exactly
match the requested font.
Clipping precision is used to specify how characters are treated when they
lie on a clipping boundary. There are three options:
CLIP_DEFAULT_PRECIS: Allows Windows to select a "reasonable" font.
This is the option selected most often and is equal to zero.
CLIP_CHARACTER_PRECIS: Requires Windows to select a font that
allows individual characters to be clipped if any part of the character
lies outside the clipping region.
CLIP_STROKE_PRECIS: Requires Windows to choose a font that allows
portions of an individual character to be clipped if a character falls
on the clipping boundary.
The output quality of the font refers to the degree to which GDI routines
must match logical font attributes to the physical representation of the
font. Here, again, there are three options:
DEFAULT_QUALITY: Appearance doesn't matter; Windows is free to
provide a "reasonable" font. This is a commonly selected option and is
equivalent to using zero as a parameter.
DRAFT_QUALITY: Fast output is given higher priority than print
quality. Some effects, such as strikethrough, bold, italic, and underlined
characters, are synthesized by GDI routines if necessary.
PROOF_QUALITY: The output quality is given higher priority than
output speed. The quality of the font is more important than exact matching
of the logical-font attributes. Some effects, such as strikethrough, bold,
italics, and underlined characters, are synthesized by GDI routines if
necessary.
Font Pitch and Family Attributes
All fonts have a certain pitch. When requesting a font from Windows, you
have three different choices for the pitch:
DEFAULT_PITCH: Windows selects a reasonable font, based on other
specified attributes.
FIXED_PITCH: The font created by Windows must have a fixed pitch.
VARIABLE_PITCH: The font is specified to have a variable pitch.
As was discussed earlier, the font family describes general characteristics
for a type of font and can be used when a specific font might not be available
on all machines. Here are the values for font families:
FF_DECORATIVE
FF_DONTCARE
FF_MODERN
FF_ROMAN
FF_SCRIPT
FF_SWISS
The pitch attribute can be combined with a font family attribute using
the bitwise OR operator, like this:
CAUTION: Combining the
pitch and family attributes isn't necessary; often, the family name implies
a pitch. In the preceding example, it's possible to specify just FF_SWISS.
FF_ROMAN and FF_SWISS always imply a variable
pitch. FF_MODERN always implies a fixed pitch. Other family types
contain fonts that have both fixed and variable pitch.
Font Weights
You can specify the relative weight of a font, based on a scale from 0
to 1,000. A weight of 400 describes a normal font, whereas 700 is used
for a bold font. If you use 0, Windows uses a reasonable default weight
for the font. Each of the weight options between 0 and 900 has a symbolic
name, as shown in Table 13.1.
Table 13.1. Symbolic names for font weights.
Symbol
Weight
FW_DONTCARE
0
FW_THIN
100
FW_EXTRALIGHT
200
FW_ULTRALIGHT
200
FW_LIGHT
300
FW_NORMAL
400
FW_REGULAR
400
FW_MEDIUM
500
FW_SEMIBOLD
600
FW_DEMIBOLD
600
FW_BOLD
700
FW_EXTRABOLD
800
FW_ULTRABOLD
800
FW_BLACK
900
FW_HEAVY
900
Although not every weight is available for every font, Windows tries
to select a font weight close to the requested value.
Other Font Attributes
It's possible to define the escapement and orientation of a font. The escapement
is the angle, in tenths of a degree, formed by a line of text in relation
to the bottom of the page. Each degree in escapement adds 10 to the parameter
value. For example, an escapement parameter value of 900 (90deg. x 10)
describes a font where each line of text is rotated 90 degrees counterclockwise.
The orientation of a font is similar to the escapement, but applies
to each character rather than to an entire line of text.
Italic, underline, and strikethrough effects are assigned by specifying
TRUE or FALSE for each of these attributes.
Finally, you can specify the typeface name. This is the name of a font
that should be a good match for the parameters specified in other parts
of the font description. If this parameter is set to NULL, Windows
uses the other parameters when searching for a font. If you specify a name,
that name is used to search for a font. If a font with that name is found,
it is used.
Creating Fonts for Windows Programs
There are two ways to create fonts using MFC. If you are creating a small
number of fonts, you can use the CFont class and its CreateFont
member function. If you're creating several similar fonts or a large number
of fonts, you can use the LOGFONT structure.
Creating a Font Using CFont
Time Saver: The first time
you consider creating a CFont object, you might be intimidated
by the large number of parameters it takes. Don't worry; most of the parameters
can actually be set to default values or zero, and the Windows font mapper
selects a font for you.
To illustrate this, Listing 13.1 creates two fonts. One font, fntArial,
uses zero for all the parameters and specifies a font name. The other font,
fntBoldSwiss, specifies many of the characteristics of a desired
font. In both cases the font mapper determines a reasonable font. Add the
source code from Listing 13.1 to the
CDCTestView::OnDraw function
in the DCTest project that was originally created in Section 11, "Device
Contexts."
TYPE: Listing 13.1. Two different ways to create
a CFont object.
CAUTION: As with all GDI
objects, you must save the original font that is returned when a new font
is selected into a device context. If you fail to select the original font
into the device context when you're finished with the DC, you will create
a resource leak.
Creating a Font Using a LOGFONT Structure
The LOGFONT structure is often used to describe a font. Just as
the LOGBRUSH structure discussed in Section 12 was used to describe
a particular brush, the LOGFONT structure is used to describe
a particular font. A LOGFONT isn't a font; it's just a description,
so it contains members for all the attributes available for a font.
Using a LOGFONT simplifies creating fonts because many of the
attributes for a series of fonts can be shared. Listing 13.2 is a version
of CDCTestView::OnDraw that uses a LOGFONT structure
to create several different fonts.
TYPE: Listing 13.2. Using a LOGFONT structure to
create fonts.
Most of the earlier version of OnDraw can remain in place; only
the middle part of the function has changed between Listings 13.1 and 13.2.
The first eight and the last five lines are the same in both versions.
Selecting and Configuring the Right Fonts
The remainder of this section discusses two ways to simplify and improve
your font-handling code: by using stock fonts provided by Windows and by
using the Font Selection common dialog box. You will also make some changes
to the DCTest example so that the user can select a font for the application.
Stock Font Objects
Just as with stock pens and brushes, discussed in Section 12, Windows maintains
a set of stock fonts. Windows provides six stock fonts:
ANSI_FIXED_FONT: A fixed-pitch system font.
ANSI_VAR_FONT: A variable-pitch system font.
DEVICE_DEFAULT_FONT: A device-dependent font. This stock object
is available only on Windows NT.
DEFAULT_GUI_FONT: The default font for user interface objects
such as menus and dialog boxes.
OEM_FIXED_FONT: The OEM-dependent fixed-pitch font.
SYSTEM_FONT: The system font.
As with other stock objects, these fonts are used through a CDC
object by calling the SelectStockObject function, passing the
stock object as a parameter, as follows:
You can change the font used by a control or any other window by calling
the CWnd::SetFont function. The SetFont function takes
a pointer to a CFont object as a parameter:
pCtrl->SetFont(fntWingDings);
If you change the font for a window, you must be careful to keep the font
that is passed as a parameter valid for as long as the window exists.
Using the Common Font Dialog Box
Like the other common dialog boxes, the Common Font dialog box enables
you, as a programmer, to easily use a commonly used dialog box in your
Windows programs. The Common Font dialog box is extremely flexible from
a user's point of view; the user can change the color, style, typeface,
and size of the font in a single dialog box. In this section, you use the
Common Font dialog box to select a font to be used in the view window.
The font is represented by a LOGFONT variable that is a member
of the CDCTestView class. After selecting a new font with the
Common Font dialog box, the LOGFONT variable is updated and the
view redrawn.
Five steps are involved in adding support for the Common Font dialog
box:
1. Add a new LOGFONT variable to the CDCTestView class.
2. Modify the CDCTestView constructor.
3. Create a new menu item for changing the font.
4. Create a function in the CDCTestView class to handle the
new menu item.
5. Modify the CDCTestView::OnDraw member function so that the
new LOGFONT variable is used when creating a font.
Just to make things interesting, you modify the OnDraw function
to display the text rotated around the center of the view.
Add a LOGFONT Variable to the CDCTestView Class
The first step is to add a LOGFONT variable to the CDCTestView
class. Although the font is created and destroyed every time the OnDraw
member function is called, the LOGFONT variable stores the current
attributes for the font selected for the view. Add this line to the attributes
section of the CDCTestView class declaration:
LOGFONT m_logFont;
The CDCTestView class constructor must initialize this variable
to a known value. Listing 13.3 contains the source code for the new version
of the CDCTestView constructor. Only the last two lines of the
source code have been added since the previous version.
TYPE: Listing 13.3. Source code to initialize the
m_logFont variable.
Using the Developer Studio resource editor, add a new menu item to the
View menu, using the values from Table 13.2.
Table 13.2. Values used for the Font menu item.
Resource ID
Caption
Member Function
ID_VIEW_FONT
&Font...
CDCTestView::OnViewFont
Use ClassWizard to add a message-handling function to the CDCTestView
class for the new menu item, using the default name of OnViewFont.
The source code for OnViewFont is shown in Listing 13.4.
TYPE: Listing 13.4. The CDCTestView::OnViewFont member
function.
} The source code in Listing 13.4 is the heart
of this example. The current LOGFONT is passed during construction
to the Common Font dialog box, which uses it as a starting point when the
dialog box is initially displayed. After the user dismisses the dialog
box, the LOGFONT will contain any modifications made by the user.
Because the LOGFONT structure doesn't store the text color, the
GetColor function is called to update any color selections made
in the Common Font dialog box.
Modify the OnDraw Member Function
The final step in this example is to use the selected font to draw a rotating
text message in the view. The
lfEscapement field from the LOGFONT
structure is used to specify the angle of the text line. The source code
in Listing 13.5 updates the font's escapement in a for loop, causing
the text to rotate.
TYPE: Listing 13.5. Displaying a rotating text message
using a LOGFONT.
} The text will rotate around the center of
the view, as shown in Figure 13.2. The font and color are updated when
a new selection is made in the Common Font dialog box.
figure 13.2
Displaying rotating text using font escapement.
Summary
In this section you learned about using fonts in Windows programs, as well
as how to use the CFont and CFontDialog classes. Sample
programs illustrated the use of the LOGFONT structure, the use
of the Common Font dialog box, and rotating fonts.
Q&A
Q I have problems determining the correct text metrics for my device
context. I call GetTextMetrics and then select my font into the
device context. What am I doing wrong?
A The GetTextMetrics function returns information about
the currently selected font--you must select the font into the device context
before calling GetTextMetrics.
Q When I change the font for a pushbutton control nothing happens--the
original font is still used to display the caption for the button. What
am I doing wrong?
A This problem is usually due to the CFont object being
destroyed before the control is destroyed. The control doesn't copy the
font passed to it during the SetFont function call--it must be
available as long as the control exists. If you change the font for a control,
you should make the CFont object a member of the CDialog
derived class that contains the control.
Workshop
The Workshop is designed to help you anticipate possible questions, review
what you've learned, and begin thinking ahead to putting your knowledge
into practice. The answers to the quiz are in Appendix B, "Quiz Answers."
Quiz
1. Give some examples of serif and sans-serif fonts.
2. What are the stock font objects maintained by Windows?
3. What is the font escapement attribute used for?
4. What is a glyph?
5. What MFC class is used to manage fonts?
6. What are the six font families?
7. What are the three pitch choices for a font?
8. What function is used to change the font used by a window?
Exercises
1. Modify the DCTest project so that a different font is used for the Color...
pushbutton.
2. Modify the DCTest project to display text metric information for
the currently selected font.