Visual C++ 6 Unleashed

Visual C++ 6 Unleashed

By MICKEY WILLIAMS and David Bennett

Working with Fonts

Much of Windows graphical output consists of text in a variety of fonts. Like pens, brushes, and regions, a GDI handle (HFONT) also represents font object instances.

The fonts and their related rendering data for each character make a considerable memory footprint for each instance of a font object. To reduce the overhead of memory and processing time required to load, initialize, and store the details for each instance of a font, Windows uses a font mapper.

Whenever a new font object is created, the font mapper looks for the nearest match of the requested characteristics from the list of installed fonts. It then constructs a font that is as close as possible to the one you have requested.

Fonts and the CFont Class

The MFC CFont class is a wrapper for the HFONT GDI object. To create a font using CFont, you first must construct a CFont object with the default constructor and then call one of the font-creation routines.

The quickest and easiest way to create a font is with CFont's CreatePointFont() function. You can pass a desired point size (in tenths of a point), a typeface name, and optionally a reference device context pointer to create the font. You should pass a pointer to the device context to create an accurate point-size match. Otherwise, the default screen device context is used (which is inaccurate when printing).

You also can use CreatePointFontIndirect() to create a font from the lfHeight member set in a LOGFONT structure.

A much more sophisticated font-creation function is CreateFont(), which lets you specify a huge number of required attributes for the font. These attributes specify the width, height, escapement, orientation, weight, effects, character set, clipping, rendering precision, font family, pitch, and typeface with its 14 parameters. The orientation and escapement attributes are closely related. The orientation attribute refers to the rotation angle of each individual character. The escapement is similar, but refers to the entire line of text. On Windows 95/98, these values must be set to the same value. On Windows NT/2000, these values may be set independently of each other.

Each of these parameters has several associated flag values to hone the type of font required. The font mapper then uses all these attributes to try to find the best matching font for the requested specifications.

You can initialize the LOGFONT structure with these specifications and pass a pointer to the LOGFONT structure to the CreateFontIndirect() function, which then creates a font and returns a font handle. This creation form is especially useful when you have enumerated the currently installed fonts with one of the font-enumeration functions, such as EnumFonts(). The callback functions for these enumerators are passed a pointer to a LOGFONT structure so that you can create a font object instance directly from it.

After a LOGFONT structure is initialized, you can fill it with the details of a font by using the GetLogFont() function.

The CFont class also has an HFONT operator to retrieve the underlying GDI handle when cast as an HFONT.

Selecting Fonts into the Device Context

As with the other GDI objects, a font must be selected into the device context before you can use it, and the previously selected font is restored after use. You must ensure that the font is not currently selected in a device context when it is deleted.

After the font is selected, it is used whenever any of the text-output functions are called.

Stock Fonts

A number of stock fonts can be selected with the SelectStockObject() function, as Table 6.8 shows.

Table 6.8. Stock Font Objects

Stock Object Flag Font Description
ANSI_FIXED_FONT ANSI fixed pitch
ANSI_VAR_FONT ANSI variable pitch
SYSTEM_FONT Current Windows system font
DEVICE_DEFAULT_FONT Device's default font
OEM_FIXED_FONT OEM's fixed-pitch font

Device Context Font Interrogation Functions

The device context has a number of member functions that let you retrieve information regarding the currently selected font.

With variable-pitch fonts, you may need to know about the average and specific widths of characters when rendered in a specific device context. You can use the GetCharWidth() function to fill an array with the widths of individual characters for non-TrueType fonts or GetABCCharWidths() for TrueType fonts.

You can find the average widths, height, and many other specific elements of a font from its TEXTMETRICS structure. The device context's GetOutputTextMetrics() function fills such a structure for you with details of the currently selected font.

You can retrieve the typeface name of the currently selected font by calling the GetTextFace() function and passing a CString object by reference to receive the typeface name.

Kerning pairs specify the width between two characters placed together in a variable-pitch font. These values often may be negative, because characters such as l and i are thin and can be placed close together. The GetKerningPairs() function can fill an array of KERNINGPAIR structures to retrieve this information.

The GetOutlineTextMetrics() function returns an array of OUTLINETEXTMETRICS structures. These structures are full of information about TrueType fonts.

Text-Rendering Functions

Many text-rendering functions are available that perform slightly different jobs in different circumstances. The simplest is TextOut(), which lets you specify an x and y coordinate and a CString holding the text to display.

The device context's text-alignment flags adjust the position of the text relative to the given coordinate. You can adjust these flags by using the SetTextAlign() function and passing a combination of the alignment flags, such as TA_TOP, TA_CENTER, TA_RIGHT, TA_LEFT, TA_BASELINE, and TA_BOTTOM. You can combine this flag value with the TA_NOUPDATECP and TA_UPDATECP to not update or update the current graphic cursor position after the text rendering. The corresponding GetTextAlign() returns the current flag settings.

You can change the color of the rendered text with the device context's SetTextColor() and SetBkColor() functions to set the foreground and background colors to a specified COLORREF value. You can make the background behind the text transparent or opaque by passing the TRANSPARENT or OPAQUE flag to the SetBkMode() function.

The ExtTextOut() function lets you clip text to a specified rectangle by using the ETO_CLIPPED flag. You can supply an array of spacing values to separate the individual character cells to ExtTextOut().

You can use TabbedTextout() to display a text string with embedded tab characters. These tabs then are expanded to positions specified by an array of consecutive tab positions relative to a specified origin.

The DrawText() function performs some quite advanced text formatting, such as word wrapping and justification. You can pass a combination of formatting flag values, such as DT_WORDBREAK, DT_LEFT, DT_RIGHT, DT_TOP, and DT_CENTER (and many others).

You can call the GrayString() function to draw grayed text using a specific graying brush and optionally pass a pointer to your own text-rendering function.

You often will want to know the dimensions required by a text string without actually rendering it. You can find these dimensions by using the GetOutputTextExtent(), GetTabbedTextExtent(), or GetOutputTabbedTextExtent() function. These functions use the device context to calculate and return a CSize object holding the size required to render the text using the currently selected font and device-context settings.

Share ThisShare This

Informit Network