HOWTO: Calculate a Bounding Rectangle For a of String TextID: Q203099
|
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.
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<iNumPts; i++) {
if (lpPoints[i].x > 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;
}
For more information on paths, what they are, and how to use them, please see the following article in the Microsoft Knowledge Base:
Q128091 SAMPLE: How to Use Paths to Create Text Effects
Additional query words: kbDSupport
Keywords :
Version : WINDOWS:
Platform : WINDOWS
Issue type : kbhowto
Last Reviewed: May 3, 1999