How To Fit Strings by Truncating with an Ellipsis (249678)



The information in this article applies to:

  • Microsoft Windows 2000 Server
  • Microsoft Windows 2000 Advanced Server
  • Microsoft Windows 2000 Professional
  • Microsoft Windows CE Operating System, Versions 2.12
  • Microsoft Windows CE Operating System, Versions 2.11
  • Microsoft Windows CE Operating System, Versions 2.0
  • Microsoft Windows CE Operating System, Versions 1.0
  • Microsoft Windows CE Operating System, Versions 3.0
  • Microsoft Windows 95
  • Microsoft Windows 98
  • Microsoft Windows 98 Second Edition
  • Microsoft Windows NT Server
  • Microsoft Windows NT Workstation
  • Microsoft Windows XP 64-Bit Edition
  • Microsoft Windows XP Home Edition
  • the operating system: Microsoft Windows XP 64-Bit Edition

This article was previously published under Q249678

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;

}
				

Modification Type:MinorLast Reviewed:5/3/2006
Keywords:kbDSWGDI2003Swept kbFont kbGDI kbhowto KB249678