Formatting Text

Because the dimensions of the system font do not change during a Windows session, you need to call GetTextMetrics only once when your program executes. A good place to make this call is while processing the WM_CREATE message in the window procedure. The WM_CREATE message is the first message the window procedure receives. Windows calls your window procedure with a WM_CREATE message when you call CreateWindow in WinMain.

Suppose you're writing a Windows program that displays several lines of text running down the client area. You'll want to obtain values for the character width and height. Within the window procedure you can define two variables to save the average character width (cxChar) and the total height (cyChar):

static short cxChar, cyChar ;

The prefix c added to the variable names stands for ”count,“ and in combination with x or y refers to a width or a height. These variables are defined as static because they must be valid when the window procedure processes other messages (such as WM_PAINT). If the variables are defined outside any functions, they need not be defined as static.

Here's the WM_CREATE code:

case WM_CREATE :

hdc = GetDC (hwnd) ;

GetTextMetrics (hdc, &tm) ;

cxChar = tm.tmAveCharWidth ;

cyChar = tm.tmHeight + tm.tmExternalLeading ;

ReleaseDC (hwnd, hdc) ;

return 0 ;

If you do not want to include external leading to space lines of text, you can use:

cyChar = tm.tmHeight ;

How you use this character size to calculate display coordinates is up to you. A simple method is to leave a cyChar margin at the top of the client area and a cxChar margin at the left. To display several lines of left-justified text, use the following x-coordinate values when calling the TextOut function:

cxChar

The y-coordinate values in TextOut are:

cyChar * (1 + i)

where i is the line number starting at 0.

You'll often find it necessary to display formatted numbers as well as simple character strings. If you were programming in MS-DOS using standard C library functions, you would probably use printf for this formatting. You cannot use printf in Windows, because printf writes to the standard output device, and that concept makes no sense under Windows.

Instead, you can use sprintf. The sprintf function works just like printf except that it puts the formatted string into a character array. You can then use TextOut to write the string to the display. Very conveniently, the value returned from sprintf is the length of the string—you can pass this value to TextOut as the nLength parameter. This code shows a typical sprintf and TextOut combination:

short nLength ;

char szBuffer [40] ;

[other program lines]

nLength = sprintf (szBuffer, "The sum of %d and %d is %d",

nA, nB, nA + nB) ;

TextOut (hdc, x, y, szBuffer, nLength) ;

For something as simple as this you could dispense with the nLength definition and combine the two statements into one:

TextOut (hdc, x, y, szBuffer,

sprintf (szBuffer, "The sum of %d and %d is %d",

nA, nB, nA + nB)) ;

It's not pretty, but it works.

If you don't need to display floating-point numbers, you can use wsprintf rather than sprintf. The wsprintf function has the same syntax as sprintf, but it's included in Windows, so using it won't increase the size of your .EXE file.