The Ex06a Example
This example sets up a view window with the logical twips mapping mode. A text string is displayed in 10-point sizes with the Arial TrueType font. Here are the steps for building the application:
Use the MFC Application Wizard to generate the Ex06a project. Start by choosing New from the File menu, and then select MFC Application. Select Single Document on the Application Type page, and deselect Printing And Print Preview on the Advanced Features page. Accept all the other default settings.
Select the CEx06aView class in Class View, and then use the Properties window to override the OnPrepareDC function in the CEx06aView class. Edit the code in

void CEx06aView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(1440, 1440);
pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX),
pDC->GetDeviceCaps(LOGPIXELSY));
}
Add a private ShowFont helper function to the view class. Add the following prototype in

private:
void ShowFont(CDC* pDC, int& nPos, int nPoints);
Then add the function itself in

void CEx06aView::ShowFont(CDC* pDC, int& nPos, int nPoints)
{
TEXTMETRIC tm;
CFont fontText;
CString strText;
CSize sizeText;
fontText.CreateFont(-nPoints * 20, 0, 0, 0, 400,
FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS, "Arial");
CFont* pOldFont = (CFont*) pDC->SelectObject(&fontText);
pDC->GetTextMetrics(&tm);
TRACE("points = %d, tmHeight = %d, tmInternalLeading = %d,"
" tmExternalLeading = %d\n", nPoints, tm.tmHeight,
tm.tmInternalLeading, tm.tmExternalLeading);
strText.Format("This is %d-point Arial", nPoints);
sizeText = pDC->GetTextExtent(strText);
TRACE("string width = %d, string height = %d\n", sizeText.cx,
sizeText.cy);
pDC->TextOut(0, nPos, strText);
pDC->SelectObject(pOldFont);
nPos += tm.tmHeight + tm.tmExternalLeading;
}
Edit the OnDraw function in

void CEx06aView::OnDraw(CDC* pDC)
{
int nPosition = 0;
for (int i = 6; i <= 24; i += 2) {
ShowFont(pDC, nPosition, i);
}
TRACE("LOGPIXELSX = %d, LOGPIXELSY = %d\n",
pDC->GetDeviceCaps(LOGPIXELSX),
pDC->GetDeviceCaps(LOGPIXELSY));
TRACE("HORZSIZE = %d, VERTSIZE = %d\n",
pDC->GetDeviceCaps(HORZSIZE),
pDC->GetDeviceCaps(VERTSIZE));
TRACE("HORZRES = %d, VERTRES = %d\n",
pDC->GetDeviceCaps(HORZRES),
pDC->GetDeviceCaps(VERTRES));
}
Build and run the Ex06a program. You must run the program from the debugger if you want to see the output from the TRACE statements. You can choose Start from the Debug menu in Visual C++ .NET, press the F5 key, or click the Continue button on the Debug toolbar (which will force the project to be built).

The resulting output (assuming the use of a standard VGA card) will look like the following:

Notice that the output string sizes don't quite correspond to the point sizes. This discrepancy results from the font engine's conversion of logical units to pixels. The program's trace output, partially shown here, shows the printout of font metrics. (The numbers depend on your display driver and your video driver.)
points = 6, tmHeight = 150, tmInternalLeading = 30, tmExternalLeading = 4
string width = 990, string height = 150
points = 8, tmHeight = 210, tmInternalLeading = 45, tmExternalLeading = 5
string width = 1380, string height = 210
points = 10, tmHeight = 240, tmInternalLeading = 45, tmExternalLeading = 6
string width = 1770, string height = 240
points = 12, tmHeight = 270, tmInternalLeading = 30, tmExternalLeading = 8
string width = 2130, string height = 270
The Ex06a Program Elements
Following is a discussion of the important elements in the Ex06a example.
Setting the Mapping Mode in the OnPrepareDC Function
The application framework calls OnPrepareDC before calling OnDraw, so the OnPrepareDC function is the logical place to prepare the device context. If you had other message handlers that needed the correct mapping mode, those functions would have contained calls to OnPrepareDC.
The ShowFont Private Member Function
ShowFont contains code that is executed 10 times in a loop. With C, you would have made this a global function, but with C++ it's better to make it a private class member function, sometimes known as a helper function. This function creates the font, selects it into the device context, prints a string to the window, and then deselects the font. If you choose to include debug information in the program, ShowFont also displays useful font metrics information, including the actual width of the string.
Calling CFont::CreateFont
This call includes lots of parameters, but the important ones are the first two— the font height and the width. A width value of 0 means that the aspect ratio of the selected font will be set to a value specified by the font designer. If you put a nonzero value here, as you'll see in the next example, you can change the font's aspect ratio.
Tip | If you want your font to be a specific point size, the CreateFont font height parameter (the first parameter) must be negative. If you're using the MM_TWIPS mapping mode for a printer, for example, a height parameter of –240 ensures a true 12-point font, with tmHeight - tmInternalLeading = 240. A +240 height parameter gives you a smaller font, with tmHeight = 240. |
The last CreateFont parameter specifies the font name, in this case the Arial TrueType font. If you had used NULL for this parameter, the FF_SWISS specification (which indicates a proportional font without serifs) would have caused Windows to select the best matching font, which, depending on the specified size, might have been the System font or the Arial TrueType font. The font name takes precedence. If you had specified FF_ROMAN (which indicates a proportional font with serifs) with Arial, for example, you would have gotten Arial.
The Ex06b Example
This program is similar to Ex06a except that it shows multiple fonts. The mapping mode is MM_ANISOTROPIC, with the scale dependent on the window size. The characters change size along with the window. This program effectively shows off some TrueType fonts and contrasts them with the old-style fonts. Here are the steps for building the application:
Run the MFC Application Wizard to generate the Ex06b project. Make it an SDI application and deselect Printing And Print Preview on the Advanced Features page.
Select the CEx06bView class in Class View, and then use the Properties window to override the OnPrepareDC function in the CEx06bView class. Edit the code in

void CEx06bView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
CRect clientRect;
GetClientRect(clientRect);
pDC->SetMapMode(MM_ANISOTROPIC); // +y = down
pDC->SetWindowExt(400, 450);
pDC->SetViewportExt(clientRect.right, clientRect.bottom);
pDC->SetViewportOrg(0, 0);
}
Add a private TraceMetrics helper function to the view class. Add the following prototype in

private:
void TraceMetrics(CDC* pDC);
Then add the function itself in

void CEx06bView::TraceMetrics(CDC* pDC)
{
TEXTMETRIC tm;
char szFaceName[100];
pDC->GetTextMetrics(&tm);
pDC->GetTextFace(99, szFaceName);
TRACE("font = %s, tmHeight = %d, tmInternalLeading = %d,"
" tmExternalLeading = %d\n", szFaceName, tm.tmHeight,
tm.tmInternalLeading, tm.tmExternalLeading);
}
Edit the OnDraw function in

void CEx06bView::OnDraw(CDC* pDC)
{
CFont fontTest1, fontTest2, fontTest3, fontTest4;
fontTest1.CreateFont(50, 0, 0, 0, 400, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS, "Arial");
CFont* pOldFont = pDC->SelectObject(&fontTest1);
TraceMetrics(pDC);
pDC->TextOut(0, 0, "This is Arial, default width");
fontTest2.CreateFont(50, 0, 0, 0, 400, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_MODERN, "Courier");
// not TrueType
pDC->SelectObject(&fontTest2);
TraceMetrics(pDC);
pDC->TextOut(0, 100, "This is Courier, default width");
fontTest3.CreateFont(50, 10, 0, 0, 400, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_ROMAN, NULL);
pDC->SelectObject(&fontTest3);
TraceMetrics(pDC);
pDC->TextOut(0, 200, "This is generic Roman, variable width");
fontTest4.CreateFont(50, 0, 0, 0, 400, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_MODERN, "LinePrinter");
pDC->SelectObject(&fontTest4);
TraceMetrics(pDC);
pDC->TextOut(0, 300, "This is LinePrinter, default width");
pDC->SelectObject(pOldFont);
}
Build and run the Ex06b program. Run the program from the debugger to see the TRACE output. The program's window is shown here:

Resize the window to make it smaller, and watch the font sizes change. Compare the following window with the previous one:

If you continue to downsize the window, notice how the Courier font stops shrinking after a certain size and how the Roman font width changes.
The Ex06b Program Elements
Following is a discussion of the important elements in the Ex06b example.
The OnDraw Member
Function The OnDraw function displays character strings in four fonts, as follows:
fontTest1 The TrueType font Arial with default width selection.
fontTest2 The old-style font Courier with default width selection. Notice how jagged the font appears in larger sizes.
fontTest3 The generic Roman font for which Windows supplies the TrueType font Times New Roman with programmed width selection. The width is tied to the horizontal window scale, so the font stretches to fit the window.
fontTest4 The LinePrinter font is specified, but because this is not a Windows font for the display, the font engine falls back on the FF_MODERN specification and selects the TrueType Courier New font.
The TraceMetrics Helper Function
The TraceMetrics helper function calls CDC::GetTextMetrics and CDC::GetText- Face to get the current font's parameters, which it prints in the Debug window.