Introduction
It is known that the DrawText
function provided by the Windows CE API does not support the DT_END_ELLIPSIS
flag. This makes it harder to emulate what the list view control does when in report mode: text cells that do not fit on the column width are displayed with a terminating ellipsis (...).
An approach to solving this problem is available here, but it is based on MFC, and I wanted an API-only version of the thing.
This article presents a very simple solution to this problem by implementing the DrawTextEx
function.
The Solution
The solution presented here is simple, straightforward and tries to preserve the spirit of the desktop version of DrawText
: provided strings must allow for changes in-place.
To make sure the developer understands this (the function will cast away the char pointer constness), an additional flag must be provided: DT_MODIFYSTRING
. Failing this, the function will make no in-place changes to the string, and no ellipsis will be shown.
After determining that the user really understands these issues, the function can start its work by calculating the string length (if it was not supplied) as well as its screen size.
If the string's screen size is larger (in this case wider) than the supplied rectangle's, it needs to be split and an ellipsis Unicode character added to the end of it. Note that the function tries to estimate where the ellipsis character will be placed in order to avoid entering a lengthy trial-and-error loop. This loop will eventually be entered only if the first size estimate is wider than the rectangle's width.
Finally, when the cut string with the appended ellipsis character does fit the specified rectangle, we can display it using the good old DrawText
function.
The Code
As you can see, the code is pretty self-explanatory. You can use it right away, or make the changes you see fit (there are plenty of those, for sure!).
#define ELLIPSIS ((TCHAR)0x2026)
int DrawTextEx(HDC hDC, LPCTSTR lpString, int nCount, LPRECT lpRect,
UINT uFormat)
{
if(uFormat & (DT_END_ELLIPSIS | DT_MODIFYSTRING))
{
SIZE szStr;
LPTSTR lpStr = (LPTSTR)lpString; int nWidth = lpRect->right - lpRect->left;
if(nCount == -1)
nCount = _tcslen(lpStr);
GetTextExtentPoint32(hDC, lpStr, nCount, &szStr);
if(szStr.cx > nWidth)
{
int nEstimate = (nCount * nWidth) / szStr.cx + 1;
if(nEstimate < nCount)
nCount = nEstimate;
lpStr[nCount-1] = ELLIPSIS;
GetTextExtentPoint32(hDC, lpStr, nCount, &szStr);
while(szStr.cx > nWidth && nCount > 1)
{
lpStr[--nCount] = 0; lpStr[nCount-1] = ELLIPSIS;
GetTextExtentPoint32(hDC, lpStr, nCount, &szStr);
}
}
uFormat &= ~(DT_END_ELLIPSIS | DT_MODIFYSTRING);
}
return DrawText(hDC, lpString, nCount, lpRect, uFormat);
}