Microsoft KB Archive/203099

{|
 * width="100%"|

HOWTO: Calculate a Bounding Rectangle For a of String Text

 * }

Q203099

-

The information in this article applies to:


 * Microsoft Win32 Software Development Kit (SDK)
 * Microsoft Windows 2000 Advanced Server
 * Microsoft Windows 2000 Server
 * Microsoft Windows 2000 Professional

-

SUMMARY
In many cases it is necessary to calculate the display area occupied by a particular text string when outputting it to a display context. The code in this article demonstrates one way of deriving this information and returning it as a bounding rectangle.

Regardless of the rotation or orientation of the text, the bounding rectangle is not rotated. The left and right sides of the bounding rectangle parallel the Y axis and the top and bottom sides parallel the X axis. It is noteworthy that the bounding rectangle that's returned represents the pixel bounds of the text's glyphs rather than the typographical extents that would be used for text formatting.

MORE INFORMATION
The following function returns a bounding rectangle for a string of text. It does this by drawing the text as a path and then retrieving the data comprising the path and scanning it for the maximum and minimum extents.

NOTE: Only True Type fonts are supported in paths so this function only works with True Type fonts.

/******************************************************************** *                                                                  *  * FUNCTION:  GetTextBoundingRect                                  * *                                                                  *  * PURPOSE:   Get a bounding rectangle for a string of text output   * *           to a specified coordinate in a DC using the currently  * *           selected font                                          * *                                                                  *  * NOTES:     The reference DC must have a True Type font selected   * *                                                                  *  *********************************************************************/   BOOL GetTextBoundingRect(HDC    hDC,   // Reference DC                           int    x,     // X-Coordinate                           int    y,     // Y-Coordinate                           LPSTR  lpStr, // The text string to evaluate                           DWORD  dwLen, // The length of the string                            LPRECT lprc)  // Holds bounding rectangle {     LPPOINT lpPoints; LPBYTE lpTypes; int i, iNumPts; // Draw the text into a path BeginPath(hDC); i = SetBkMode(hDC, TRANSPARENT); TextOut(hDC, x, y, lpStr, dwLen); SetBkMode(hDC, i); EndPath(hDC); // How many points are in the path iNumPts = GetPath(hDC, NULL, NULL, 0); if (iNumPts == -1) return FALSE; // Allocate room for the points lpPoints = (LPPOINT)GlobalAlloc(GPTR, sizeof(POINT) * iNumPts); if (!lpPoints) return FALSE; // Allocate room for the point types lpTypes = GlobalAlloc(GPTR, iNumPts); if (!lpTypes) { GlobalFree(lpPoints); return FALSE; }     // Get the points and types from the current path iNumPts = GetPath(hDC, lpPoints, lpTypes, iNumPts); // Even more error checking if (iNumPts == -1) { GlobalFree(lpTypes); GlobalFree(lpPoints); return FALSE; }     // Initialize the rectangle SetRect(lprc, 0xFFFFF, 0xFFFFF, 0, 0);

// Get the maximum/minimum extents from the path data for (i=0; i lprc->right) lprc->right  = lpPoints[i].x;          if (lpPoints[i].y > lprc->bottom) lprc->bottom = lpPoints[i].y;          if (lpPoints[i].x < lprc->left)   lprc->left   = lpPoints[i].x;          if (lpPoints[i].y < lprc->top)    lprc->top    = lpPoints[i].y;      } GlobalFree(lpTypes); GlobalFree(lpPoints); return TRUE; }