在Windows编程中,使用Win32 API函数GetTextExtentPoint32
或DrawText
函数并设置DT_CALCRECT
标志,并不能正确地告诉斜体文本的宽度。这些函数计算出的高度是正确的,但宽度往往过窄,导致显示的文本看起来像是被右修剪了。
可以尝试使用GetCharABCWidths
或GetCharABCWidthsFloat
Win32 API函数。这些函数将提供感兴趣的文本中每个字符的悬挂和溢出信息。
为了更详细地了解如何使用悬挂和溢出值,请查阅以下MSDN文章:
字符宽度
这个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像素。