Font enumeration is the process of obtaining from GDI a list of all fonts available on a device. A program can then select one of these fonts or display them in a dialog box for selection by the
In the old days of
EnumFonts (hdc, szTypeFace, EnumProc, pData) ;
A program could enumerate all fonts (by setting the second argument to NULL) or just those of a particular typeface. The third argument is an enumeration callback function; the fourth argument is optional data passed to that function. GDI calls the callback function once for each font in the system, passing to it both
The EnumFontFamilies function was designed to better enumerate TrueType fonts under Windows 3.1:
EnumFontFamilies (hdc, szFaceName, EnumProc, pData) ;
Generally,
EnumFontFamilies
is called first with a NULL second argument. The
EnumProc
callback function is called once for each font family (such as Times New Roman). Then the application calls
EnumFontFamilies
again with that typeface name and a different callback function. GDI calls the second callback function for each font in the family (such as Times New Roman Italic). The callback function is passed an ENUMLOGFONT structure (which is a LOGFONT structure plus a "full name" field and a "style" field containing, for example, the text
The EnumFontFamiliesEx function is recommended for applications running under the 32-bit versions of Windows:
EnumFontFamiliesEx (hdc, &logfont, EnumProc, pData, dwFlags) ;
The second argument is a pointer to a LOGFONT structure for which the
lfCharSet
and
lfFaceName
fields
We had a little introduction to the
ChooseFont
common dialog box back in Chapter 11. Now that we've
The CHOSFONT program, shown in Figure 17-7,
Figure 17-7. The CHOSFONT program.
CHOSFONT.C
/*-----------------------------------------
CHOSFONT.C -- ChooseFont Demo
(c) Charles Petzold, 1998
-----------------------------------------*/
#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("ChosFont") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("ChooseFont"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CHOOSEFONT cf ;
static int cyChar ;
static LOGFONT lf ;
static TCHAR szText[] = TEXT ("\x41\x42\x43\x44\x45 ")
TEXT ("\x61\x62\x63\x64\x65 ")
TEXT ("\xC0\xC1\xC2\xC3\xC4\xC5 ")
TEXT ("\xE0\xE1\xE2\xE3\xE4\xE5 ")
#ifdef UNICODE
TEXT ("\x0390\x0391\x0392\x0393\x0394\x0395 ")
TEXT ("\x03B0\x03B1\x03B2\x03B3\x03B4\x03B5 ")
TEXT ("\x0410\x0411\x0412\x0413\x0414\x0415 ")
TEXT ("\x0430\x0431\x0432\x0433\x0434\x0435 ")
TEXT ("\x5000\x5001\x5002\x5003\x5004")
#endif
;
HDC hdc ;
int y ;
PAINTSTRUCT ps ;
TCHAR szBuffer [64] ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
// Get text height
cyChar = HIWORD (GetDialogBaseUnits ()) ;
// Initialize the LOGFONT structure
GetObject (GetStockObject (SYSTEM_FONT), sizeof (lf), &lf) ;
// Inialize the CHOOSEFONT structure
cf.lStructSize = sizeof (CHOOSEFONT) ;
cf.hwndOwner = hwnd ;
cf.hDC = NULL ;
cf.lpLogFont = &lf ;
cf.iPointSize = 0 ;
cf.Flags = CF_INITTOLOGFONTSTRUCT
CF_SCREENFONTS CF_EFFECTS ;
cf.rgbColors = 0 ;
cf.lCustData = 0 ;
cf.lpfnHook = NULL ;
cf.lpTemplateName = NULL ;
cf.hInstance = NULL ;
cf.lpszStyle = NULL ;
cf.nFontType = 0 ;
cf.nSizeMin = 0 ;
cf.nSizeMax = 0 ;
return 0 ;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_FONT:
if (ChooseFont (&cf))
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
}
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
// Display sample text using selected font
SelectObject (hdc, CreateFontIndirect (&lf)) ;
GetTextMetrics (hdc, &tm) ;
SetTextColor (hdc, cf.rgbColors) ;
TextOut (hdc, 0, y = tm.tmExternalLeading, szText, lstrlen (szText)) ;
// Display LOGFONT structure fields using system font
DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
SetTextColor (hdc, 0) ;
TextOut (hdc, 0, y += tm.tmHeight, szBuffer,
wsprintf (szBuffer, TEXT ("lfHeight = %i"), lf.lfHeight)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfWidth = %i"), lf.lfWidth)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfEscapement = %i"),
lf.lfEscapement)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfOrientation = %i"),
lf.lfOrientation)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfWeight = %i"), lf.lfWeight)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfItalic = %i"), lf.lfItalic)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfUnderline = %i"), lf.lfUnderline)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfStrikeOut = %i"), lf.lfStrikeOut)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfCharSet = %i"), lf.lfCharSet)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfOutPrecision = %i"),
lf.lfOutPrecision)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfClipPrecision = %i"),
lf.lfClipPrecision)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfQuality = %i"), lf.lfQuality)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfPitchAndFamily = 0x%02X"),
lf.lfPitchAndFamily)) ;
TextOut (hdc, 0, y += cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("lfFaceName = %s"), lf.lfFaceName)) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
|
CHOSFONT.RC
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
// Menu
CHOSFONT MENU DISCARDABLE
BEGIN
MENUITEM "&Font!", IDM_FONT
END
|
RESOURCE.H// Microsoft Developer Studio generated include file. // Used by ChosFont.rc #define IDM_FONT 40001 |
As usual with the common dialog boxes, a Flags field in the CHOOSEFONT structure lets you pick lots of options. The CF_INITLOGFONTSTRUCT flag that CHOSFONT specifies causes Windows to initialize the dialog box selection based on the LOGFONT structure passed to the ChooseFont structure. You can use flags to specify TrueType fonts only (CF_TTONLY) or fixed-pitch fonts only (CF_FIXEDPITCHONLY) or no symbol fonts (CF_SCRIPTSONLY). You can display screen fonts (CF_SCREENFONTS), printer fonts (CF_PRINTERFONTS), or both (CF_BOTH). In the latter two cases, the hDC field of the CHOOSEFONT structure must reference a printer device context. The CHOSFONT program uses the CF_SCREENFONTS flag.
The CF_EFFECTS flag (the third flag that the CHOSFONT program uses) forces the dialog box to include check boxes for underlining and strikeout and also allows the selection of a text color. It's not hard to implement text
Notice the Script field in the Font dialog displayed by ChooseFont . This lets the user select a character set available for the particular font; the appropriate character set ID is returned in the LOGFONT structure.
The
ChooseFont
function uses the logical inch to calculate the
lfHeight
field from the point
Good. That's probably what we want. But keep the following in mind:
Fortunately, the CHOOSEFONT structure includes an iPointSize field that provides the size of the selected font in units of 1/10 of a point. Regardless of the device context and mapping mode, you can always convert this field to a logical size and use that for the lfHeight field. The appropriate code can be found in the EZFONT.C file. You can probably simplify it based on your needs.
Another program that uses
ChooseFont
is UNICHARS, shown in Figure 17-8. This program lets you view all the
Figure 17-8. The UNICHARS program.
UNICHARS.C
/*-----------------------------------------------
UNICHARS.C -- Displays 16-bit character codes
(c) Charles Petzold, 1998
-----------------------------------------------*/
#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("UniChars") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requies Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Unicode Characters"),
WS_OVERLAPPEDWINDOW WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CHOOSEFONT cf ;
static int iPage ;
static LOGFONT lf ;
HDC hdc ;
int cxChar, cyChar, x, y, i, cxLabels ;
PAINTSTRUCT ps ;
SIZE size ;
TCHAR szBuffer [8] ;
TEXTMETRIC tm ;
WCHAR ch ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
lf.lfHeight = - GetDeviceCaps (hdc, LOGPIXELSY) / 6 ; // 12 points
lstrcpy (lf.lfFaceName, TEXT ("Lucida Sans Unicode")) ;
ReleaseDC (hwnd, hdc) ;
cf.lStructSize = sizeof (CHOOSEFONT) ;
cf.hwndOwner = hwnd ;
cf.lpLogFont = &lf ;
cf.Flags = CF_INITTOLOGFONTSTRUCT CF_SCREENFONTS ;
SetScrollRange (hwnd, SB_VERT, 0, 255, FALSE) ;
SetScrollPos (hwnd, SB_VERT, iPage, TRUE ) ;
return 0 ;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_FONT:
if (ChooseFont (&cf))
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
}
return 0 ;
case WM_VSCROLL:
switch (LOWORD (wParam))
{
case SB_LINEUP: iPage -= 1 ; break ;
case SB_LINEDOWN: iPage += 1 ; break ;
case SB_PAGEUP: iPage -= 16 ; break ;
case SB_PAGEDOWN: iPage += 16 ; break ;
case SB_THUMBPOSITION: iPage = HIWORD (wParam) ; break ;
default:
return 0 ;
}
iPage = max (0, min (iPage, 255)) ;
SetScrollPos (hwnd, SB_VERT, iPage, TRUE) ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, CreateFontIndirect (&lf)) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmMaxCharWidth ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
cxLabels = 0 ;
for (i = 0 ; i < 16 ; i++)
{
wsprintf (szBuffer, TEXT (" 000%1X: "), i) ;
GetTextExtentPoint (hdc, szBuffer, 7, &size) ;
cxLabels = max (cxLabels, size.cx) ;
}
for (y = 0 ; y < 16 ; y++)
{
wsprintf (szBuffer, TEXT (" %03X_: "), 16 * iPage + y) ;
TextOut (hdc, 0, y * cyChar, szBuffer, 7) ;
for (x = 0 ; x < 16 ; x++)
{
ch = (WCHAR) (256 * iPage + 16 * y + x) ;
TextOutW (hdc, x * cxChar + cxLabels,
y * cyChar, &ch, 1) ;
}
}
DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
|
UNICHARS.RC
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
// Menu
UNICHARS MENU DISCARDABLE
BEGIN
MENUITEM "&Font!", IDM_FONT
END
|
RESOURCE.H// Microsoft Developer Studio generated include file. // Used by Unichars.rc #define IDM_FONT 40001 |