精确计算斜体文本宽度的方法

在Windows编程中,使用Win32 API函数GetTextExtentPoint32DrawText函数并设置DT_CALCRECT标志,并不能正确地告诉斜体文本的宽度。这些函数计算出的高度是正确的,但宽度往往过窄,导致显示的文本看起来像是被右修剪了。

可以尝试使用GetCharABCWidthsGetCharABCWidthsFloat Win32 API函数。这些函数将提供感兴趣的文本中每个字符的悬挂和溢出信息。

为了更详细地了解如何使用悬挂和溢出值,请查阅以下MSDN文章:

  • INFO: Calculating Text Extents of Bold and Italic Text
  • HOWTO: Mix Italic and Regular (Non-Italic) Text (下载压缩的旧Microsoft KB文章)
  • How To Fit Text in a Rectangle
  • INFO: Using GetCharABCWidths() to Calculate Text Extents

字符宽度

这个EXE的新版本包括一个新的复选框,可以看到添加“最后一个字符的溢出”将如何帮助获得更准确的结果。

然而,在本文中,建议另一种方法:

在内存设备上下文(填充为白色)中以黑色绘制文本,如下所示:

SIZE sizeText; // 使用经典方法计算文本宽度 GetTextExtentPoint32(hDCMem, szText, lstrlen(szText), &sizeText); // 计算最后一个字符的宽度,如'oupoi'建议 SIZE sizeLastCharacter; GetTextExtentPoint32(hDCMem, &szText[-1 + lstrlen(szText)], 1, &sizeLastCharacter); // 设置一个足够宽的边界矩形以适应绘制的文本 RECT rect = { 0, 0, sizeText.cx + sizeLastCharacter.cx, sizeText.cy }; // 用白色填充背景,然后以黑色绘制文本 FillRect(hDCMem, ▭, (HBRUSH)GetStockObject(WHITE_BRUSH)); DrawText(hDCMem, szText, -1, ▭, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX);

然后,从右到左扫描内存设备上下文中的像素颜色,如下所示:

int iXmax = 0; BOOL bFound = FALSE; for (int x = rect.right - 1; x >= 0 && !bFound; x--) { for (int y = 0; y <= rect.bottom - 1 && !bFound; y++) { COLORREF rgbColor = GetPixel(hDCMem, x, y); if (rgbColor != RGB(255, 255, 255)) { // 找到一个非白色像素,保存水平位置并退出循环。工作完成。 iXmax = x; bFound = TRUE; } } } // 这是绘制的斜体文本的宽度! LONG lWidthOfText = iXmax + 1; // +1因为使用0基索引

一些评论:

  • 绘制的文本可能比使用GetTextExtentPoint32计算的文本更窄。例如,Verdana 12 Italic。
  • 在对话框中,编辑控件有左右和上下边距需要考虑。在这个示例中没有使用编辑控件。
  • 在对话框中,标签控件似乎比使用SS_SIMPLE样式宽1像素。
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485