文本绘制与省略号处理

在图形用户界面(GUI)开发中,经常会遇到文本绘制的问题。当文本内容超出了显示区域,如何优雅地处理这种情况,是提升用户体验的关键。一种常见的做法是在文本末尾添加省略号(…),以表示文本被截断。本文将介绍一种实现这一功能的方法,通过自定义DrawTextEx函数来实现文本的绘制与省略号的添加。

问题描述

在Windows操作系统中,列表视图控件(list view control)在报表模式(report mode)下,如果文本单元格(text cells)的宽度不足以显示全部文本,通常会在末尾添加省略号(...)。然而,要模拟这种行为并不简单,尤其是在不使用MFC(Microsoft Foundation Classes)的情况下。

解决方案

本文提出的解决方案简单直接,旨在保持桌面版本DrawText函数的精神。首先,需要提供一个额外的标志位:DT_MODIFYSTRING。这个标志位的作用是告知函数,字符串允许在原地进行修改。如果开发者没有提供这个标志位,函数将不会对字符串进行任何原地修改,也不会显示省略号。

在确保开发者理解了这一点之后,函数开始工作。首先计算字符串的长度(如果未提供),以及其在屏幕上的大小。如果字符串的屏幕大小(宽度)大于提供的矩形区域,就需要将其分割,并在末尾添加一个省略号Unicode字符。函数会尝试估计省略号字符的位置,以避免进入一个漫长的试错循环。只有在第一次大小估计比矩形区域的宽度还要宽时,才会进入这个循环。

最后,当带有附加省略号字符的截断字符串能够适应指定的矩形区域时,就可以使用传统的DrawText函数来显示它了。

代码实现

#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); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485