【发布时间】:2015-05-19 23:42:42
【问题描述】:
我希望找到在 Windows 中呈现的文本的确切高度。我已经尝试过 GetTextExtentPoint32 和使用 DT_CALCRECT 标志调用 DrawText 并且都给出了相同的结果。
似乎返回的高度是基于整个单元格的高度,而不考虑要绘制的实际文本。
下面的代码是标准 Visual Studio 2013 Win32 项目的 WM_PAINT 处理程序。它创建一个(大)字体并绘制示例文本。文字最高部分为98像素,但GetTextExtentPoint32返回的值为131。
我意识到有些应用程序可能需要完整的单元格高度,但也有些应用程序(比如我的)只需要文本使用的 实际 高度。
有人知道如何找到这些信息吗?
是的,我可以渲染到内存 DC 并向下扫描以寻找第一个非背景颜色的像素——但这会非常慢。
谢谢
case WM_PAINT:
{
hdc = BeginPaint (hWnd, &ps);
HFONT hfont = CreateFont (-99, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH, L"Segoe UI Semibold");
auto old_hfont = SelectObject (hdc, hfont);
wchar_t sample_text[] = L"123 Testing 123";
size_t sample_text_length = wcslen (sample_text);
SIZE s;
GetTextExtentPoint32 (hdc, sample_text, sample_text_length, &s);
RECT r = {10, 10, 10 + s.cx, 10 + s.cy};
SetBkColor (hdc, RGB (80, 120, 160));
SetTextColor (hdc, RGB (220, 220, 220));
DrawText (hdc, sample_text, sample_text_length, &r, DT_SINGLELINE | DT_NOPREFIX | DT_LEFT | DT_TOP);
SelectObject (hdc, old_hfont);
DeleteObject (hfont);
EndPaint (hWnd, &ps);
break;
}
【问题讨论】:
-
在抗锯齿字体上,您的确切高度是多少?
-
DrawText 操作写入的光栅线总数?我的意思是写入的第一条和最后一条光栅线之间的高度
-
出于好奇,您能否提供有关此用例的更多详细信息? My guy instinct says that there may be a better way to solve your actual problem.
-
在尝试解决这些问题时,您会发现一件事是,您正在编写的代码表面上会执行所有所需的逻辑,以使用所有字距调整和偏移以及其他排版魔法(包括在希伯来语和其他语言中发现的所有具有重叠字符的魔法)。你会用你的一生来努力把它做好。我建议只使用 DT_CALCRECT。你的结果将是一致的,周围有干净的填充,它是一行代码而不是数千行。
-
对于像 Anthony 和 Marc 这样的名字,我猜您希望摆脱英文文本上方看似很大的空白。保留用于重音和变音符号,(几乎)在英文文本中不存在。在示例代码中它占用了 32 个像素,非常明显。只需从 Y 位置减去 TEXTMETRICS.tmInternalLeading。小心不要在上面涂上任何东西。