CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 1 of 1

Hybrid View

  1. #1
    Join Date
    Feb 2000
    Location
    Indore, India
    Posts
    1,046

    Windows SDK GDI: How do I choose a font size to exactly fit a string in a

    Q: How do I choose a font size to exactly fit a string in a given rectangle?

    A: Choosing font width and height by calculating the rectangle width and height will not solve this problem perfectly. This will only give a font which approximately fit in the rectangle, since characters are of different widths.

    In this method, calculating the font size is done in two steps. First, rough font width and height are calculated from rectangle dimensions. This font is then selected for the display device context and exact width and height is determined. From this actual font dimensions, required font dimensions are calculated by proportionately sizing the font.

    When you output multiple lines, some space is left between characters in subsequent lines ('tmExternalLeading' of 'TEXTMETRIC' structure). While evaluating the font size, this is also taken into account.

    The method is wrapped into a function 'TextOut()'. This is similar to the SDK function 'TextOut', but differs in the type of arguments. First argument is handle to device context, similar to the SDK function. Second and third arguments are pointer to the rectangle and character array respectively. Here is the code, with comments sprinkled liberally:


    Code:
    void TextOut(HDC hdc, LPRECT lprect, LPSTR lpstr)
    {
      // Gets current font
      HFONT hFont = (HFONT) GetCurrentObject(hdc, OBJ_FONT);
    
      // Gets LOGFONT structure corresponding to current font
      LOGFONT LogFont;
      if (GetObject(hFont, sizeof(LOGFONT), &LogFont) == 0)
        return;
    
      // Calculates span of the string sets rough font width and height
      int Len = strlen(lpstr);
      int Width = lprect->right - lprect->left;
      LogFont.lfWidth = -MulDiv(Width / Len, GetDeviceCaps(hdc, LOGPIXELSX), 72);
      int Height = lprect->bottom - lprect->top;
      LogFont.lfHeight = -MulDiv(Height, GetDeviceCaps(hdc, LOGPIXELSY), 72);
    
      // Creates and sets font to device context
      hFont = CreateFontIndirect(&LogFont);
      HFONT hOldFont = (HFONT) SelectObject(hdc, hFont);
    
      // Gets the string span and text metrics with current font
      SIZE Size;
      GetTextExtentExPoint(hdc, lpstr, strlen(lpstr), Width, NULL, NULL, &Size);
      TEXTMETRIC TextMetric;
      GetTextMetrics(hdc, &TextMetric);
      int RowSpace = TextMetric.tmExternalLeading;
    
      // Deselects and deletes rough font
      SelectObject(hdc, hOldFont);
      DeleteObject(hFont);
    
      // Updates font width and height with new information of string span
      LogFont.lfWidth = MulDiv(LogFont.lfWidth, Width, Size.cx);
      LogFont.lfHeight = MulDiv(LogFont.lfHeight, Height, Size.cy - RowSpace);
    
      // Creates and selects font of actual span filling the rectangle
      hFont = CreateFontIndirect(&LogFont);
      SelectObject(hdc, hFont);
    
      // Performs displaying text
      TextOut(hdc, lprect->left, lprect->top - RowSpace, lpstr, strlen(lpstr));
    
      // Select the original font and deletes the new font
      SelectObject(hdc, hOldFont);
      DeleteObject(hFont);
    }
    Result is shown in the attached image. Rectangle is shown in gray shade over which the string is output in transparent mode.


    Attached Images Attached Images  
    Last edited by Andreas Masur; April 2nd, 2006 at 04:15 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured