The EX05A 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:

  1. Run AppWizard to generate the EX05A project. Start by choosing New from the File menu, and then select MFC AppWizard (exe) on the Project tab. Select Single Document and deselect Printing And Print Preview; accept all the other default settings. The options and the default class names are shown in the following illustration.

    1. Use ClassWizard to override the OnPrepareDC function in the CEx05aView class. Edit the code in ex05aView.cpp as follows:

      void CEx05aView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
      {
          pDC->SetMapMode(MM_ANISOTROPIC);
          pDC->SetWindowExt(1440, 1440);
          pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX),
                              -pDC->GetDeviceCaps(LOGPIXELSY));
      }
      

    2. Add a private ShowFont helper function to the view class. Add the prototype shown below in ex05aView.h:

      private:
          void ShowFont(CDC* pDC, int& nPos, int nPoints);

      Then add the function itself in ex05aView.cpp:

      void CEx05aView::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;
      }
      

    3. Edit the OnDraw function in ex05aView.cpp. AppWizard always generates a skeleton OnDraw function for your view class. Find the function, and replace the code with the following:

      void CEx05aView::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));
      }
      

    4. Build and run the EX05A program. You must run the program from the debugger if you want to see the output from the TRACE statements. You can choose Go from the Start Debug submenu of the Build menu in Visual C++, or click the following button on the Build toolbar.

      The resulting output (assuming the use of a standard VGA card) looks like the screen shown here.

      Click to view at full size.

      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 below, 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 EX05A Program Elements

    Following is a discussion of the important elements in the EX05A example.

    Setting the Mapping Mode in the OnPrepareDC Function

    The application framework calls OnPrepareDC prior to 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 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.

    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 choose 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.