18.4.2 Enumerating Fonts

An application can discover which fonts are available for a given device by using the EnumFonts or EnumFontFamilies function. These functions send information about the available fonts to a callback function that the application supplies. The callback function receives information in LOGFONT and NEWTEXTMETRIC structures. (The NEWTEXTMETRIC structure contains information about a TrueType font. When the callback function receives information about a non-TrueType font, the information is contained in a TEXTMETRIC structure.) By using this information, an application can allow the user to choose among only those fonts that are available.

The EnumFontFamilies function is similar to the EnumFonts function but includes some extra functionality. New and upgrading applications should use EnumFontFamilies instead of EnumFonts. EnumFontFamilies allows an application to take advantage of the style name that is available with TrueType fonts.

In previous versions of Windows, the only style attributes were weight and italic; any other styles were specified in the family name for the font. If an application used the EnumFonts function to query the available Courier fonts, for example, EnumFonts might return information for Courier, Courier Bold, Courier Bold Italic, and Courier Italic, but it would not return information about any other Courier fonts that might be installed, because any other Courier fonts would typically have a different family name.

TrueType fonts are organized around a family name (for example, Courier New) and style names (for example, italic, bold, and extra-bold). The EnumFontFamilies function enumerates all the styles associated with a given family name, not simply the bold and italic attributes; if the system included a TrueType font called Courier New Extra-Bold, EnumFontFamilies would list it with the other Courier New fonts. The capabilities of EnumFontFamilies are helpful for fonts with many or unusual styles and for fonts that cross international borders. (Because a style name often changes with the language spoken in a country, an application that depends on the EnumFonts function could enumerate fonts whose names would change from country to country, while EnumFontFamilies would continue to enumerate the font families correctly.)

If an application does not supply a typeface name, the EnumFonts and EnumFontFamilies functions supply information about one font in each available family. To enumerate all the fonts in a device context, an application can specify NULL for the typeface name, compile a list of the available typefaces, and then enumerate each font in each typeface.

The following example uses the EnumFontFamilies function to retrieve the number of available raster, vector, and TrueType fonts:

    FONTENUMPROC lpEnumFamCallBack;
    UINT uAlignPrev;
    int aFontCount[] = { 0, 0, 0 };
    char szCount[8];

    lpEnumFamCallBack = (FONTENUMPROC) MakeProcInstance(
        (FARPROC) EnumFamCallBack, hinstApp);
    EnumFontFamilies(hdc, NULL, lpEnumFamCallBack,
        (LPARAM) aFontCount);
    FreeProcInstance((FARPROC) lpEnumFamCallBack);

    uAlignPrev = SetTextAlign(hdc, TA_UPDATECP);

    MoveTo(hdc, 10, 50);
    TextOut(hdc, 0, 0, "Number of raster fonts: ", 24);
    itoa(aFontCount[0], szCount, 10);
    TextOut(hdc, 0, 0, szCount, strlen(szCount));

    MoveTo(hdc, 10, 75);
    TextOut(hdc, 0, 0, "Number of vector fonts: ", 24);
    itoa(aFontCount[1], szCount, 10);
    TextOut(hdc, 0, 0, szCount, strlen(szCount));

    MoveTo(hdc, 10, 100);
    TextOut(hdc, 0, 0, "Number of TrueType fonts: ", 26);
    itoa(aFontCount[2], szCount, 10);
    TextOut(hdc, 0, 0, szCount, strlen(szCount));

    SetTextAlign(hdc, uAlignPrev);
        .
        .
        .

BOOL FAR PASCAL EnumFamCallBack(lplf, lpntm, FontType, aFontCount)
LPLOGFONT lplf;
LPNEWTEXTMETRIC lpntm;
short FontType;
LPSTR aFontCount;
{
    int far * aiFontCount = (int far *) aFontCount;

    if (FontType & RASTER_FONTTYPE)
        aiFontCount[0]++;
    else if (FontType & TRUETYPE_FONTTYPE)
        aiFontCount[2]++;
    else
        aiFontCount[1]++;


    if (aiFontCount[0] || aiFontCount[1] || aiFontCount[2])
        return TRUE;
    else
        return FALSE;
}

This example uses two masks, RASTER_FONTTYPE and TRUETYPE_FONTTYPE, to determine the type of font being enumerated. If the RASTER_FONTTYPE bit is set, the font is a raster font. If the TRUETYPE_FONTTYPE bit is set, the font is a TrueType font. If neither bit is set, the font is a vector font. A third mask, DEVICE_FONTTYPE, is set when a device (for example, a laser printer) supports downloading TrueType fonts; it is zero if the device is a display adapter, dot-matrix printer, or other raster device. An application can also use the DEVICE_FONTTYPE mask to distinguish GDI-supplied raster fonts from device-supplied fonts. GDI can simulate bold, italic, underline, and strikeout attributes for GDI-supplied raster fonts, but not for device-supplied fonts.

An application can also check bit 1 and 2 in the tmPitchandFamily member of the NEWTEXTMETRIC structure to identify a TrueType font. If bit 1 is zero and bit 2 is 1, the font is a TrueType font.

Vector fonts are categorized as OEM_CHARSET instead of ANSI_CHARSET. Some applications identify vector fonts by using this information, checking the tmCharSet member of the NEWTEXTMETRIC structure. This categorization usually prevents the font mapper from choosing vector fonts unless they are specifically requested. (Most applications do not use vector fonts, because they are slow and generally unattractive, and because TrueType fonts offer many of the same scaling and rotation features that required the use of vector fonts in earlier versions of Windows.)