How To Fit Strings by Truncating with an Ellipsis

Support for Windows XP has ended

Microsoft ended support for Windows XP on April 8, 2014. This change has affected your software updates and security options. Learn what this means for you and how to stay protected.

This article has been archived. It is offered "as is" and will no longer be updated.
Summary
This article presents an algorithm and sample source code to fit a string drawn within a rectangle by abbreviation with an ellipsis.
More information
Software Developers may require that code draw a string that is truncated with an ellipsis, as seen in the Windows Explorer shell or as is drawn by the DrawText function when the DT_END_ELLIPSIS flag is passed.

Usually, the DrawText function with the DT_END_ELLIPSIS flag can be used to draw such a string. However, situations may occur where this feature of the DrawText function is not available. For example, the DT_END_ELLIPSIS feature is not implemented on Windows CE and the DrawText function does not work with rotated fonts on any platform.

In these situations, a software developer must write his or her own. The following is an algorithm for truncating a string to fit a rectangle with three periods, to represent an ellipsis character:

Algorithm

  1. Determine how many characters, nFit, will fit within a given rectangle.
  2. Truncate the string with ellipsis characters immediately following the last character that fits at nFit.
  3. Test to see whether the modified string will fit the rectangle.
  4. If the string does not fit the rectangle, decrement nFit and repeat with step 2.
The following sample code implements this algorithm. Note that the code uses three periods (...) to represent an ellipsis character. If a Unicode font is known to contain an ellipsis character, it could be used in place of the string of periods.

This code also assumes that a nonrotated font is used. To modify the code to work with a rotated font, the lpRect parameter must be changed to a scaler width or another datatype that does not assume alignment with the coordinate space axis. Also, the clipping that is used in the ExtTextOut function call must be dropped in favor of another method, such as a clipping region.

Sample Code

BOOL TextOutEllipsis(HDC hDC, LPCTSTR lpString, int nCount, LPRECT lpRect){    SIZE    Size;    int     nFit;    int     nWidth = lpRect->right-lpRect->left;    LPTSTR  lpEllipsisString = NULL;    BOOL    fSuccess = FALSE;    if (lpRect)    {        // Get how many chars will fit.        fSuccess = GetTextExtentExPoint( hDC,             lpString,             lstrlen(lpString),             nWidth,             &nFit,             NULL,             &Size);                // Get the dimensions of the full string.        if (fSuccess)        {            fSuccess = GetTextExtentExPoint( hDC,                 lpString,                 lstrlen(lpString),                 nWidth,                 NULL,                 NULL,                 &Size);        }                // Allocate space for text that fits, NULL, and Ellipsis.        // Note that this is max we need, the result is always <=.        // Regardless of success this always must be deleted.        lpEllipsisString = (LPTSTR) new TCHAR[nFit + 1 + 3];        if (fSuccess && lpEllipsisString != NULL)        {            // Copy to our working buffer.            memcpy( lpEllipsisString, lpString, nFit*sizeof(TCHAR) );            lpEllipsisString[nFit] = '\0';            // If we need Ellipsis'.            while (Size.cx > nWidth && fSuccess && nFit > 0)            {                // Add them to what will fit and try again.                lstrcpy( &lpEllipsisString[nFit], TEXT("...") );                if (!GetTextExtentExPoint( hDC,                     lpEllipsisString,                     lstrlen(lpEllipsisString),                     nWidth,                     NULL,                     NULL,                     &Size))                {                    fSuccess = FALSE;                }                nFit--; // Decrement in case we need another pass.                // Rectangle too small.                if (nFit <= 0)                    fSuccess = FALSE;            }            // Working buffer now contains the string for ExtTextOut.        }    }    // Else no rectangle so fall out of the rest of this function.    if (fSuccess)    {        // We have a string with ellipsis that fits the rect.        fSuccess = ExtTextOut( hDC,                 lpRect->left,                 lpRect->top,                 ETO_CLIPPED,                 lpRect,                 lpEllipsisString,                 lstrlen( lpEllipsisString ),                 NULL );    }        // Clean up.    if (lpEllipsisString != NULL)        delete [] lpEllipsisString;    return fSuccess;}				
Note This is a "FAST PUBLISH" article created directly from within the Microsoft support organization. The information contained herein is provided as-is in response to emerging issues. As a result of the speed in making it available, the materials may include typographical errors and may be revised at any time without notice. See Terms of Use for other considerations.
Properties

Article ID: 249678 - Last Review: 01/12/2015 16:37:01 - Revision: 1.0

Microsoft Windows 2000 Server, Microsoft Windows 2000 Advanced Server, Microsoft Windows 2000 Professional Edition, Microsoft Windows CE 2.0 for the Handheld PC, Microsoft Windows CE 1.0, Microsoft Windows CE 3.0 for the Handheld PC, Microsoft Windows 95, Microsoft Windows XP Professional x64 Edition, Microsoft Windows XP Home Edition

  • kbnosurvey kbarchive kbdswgdi2003swept kbfont kbgdi kbhowto KB249678
Feedback