- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想知道哪些指标用于计算正确的行高(2 个相邻文本行基线之间的垂直距离)。 “正确”应任意定义为“无论 DrawTextW
做什么”。
The accepted answer here似乎遵循图表提供的内容in this MSDN article说:
TEXTMETRICW.tmHeight + TEXTMETRICW.tmExternalLeading;
但这似乎不正确。使用 2 段文本进行一些测试,每段文本由 2 行组成:
// RECT rc is more than large enough to fit any text
int HeightChinese = DrawTextW(hdc, L"中\r\n文", -1, &rc, 0);
int HeightLatin = DrawTextW(hdc, L"Latin,\r\nlatin!", -1, &rc, 0);
预期的返回值应该是2 * <SomethingUnknown>
.
一个观察结果是 DrawTextW
的返回值将始终匹配 RECT
输出如果 DT_CALCRECT
用于我机器上的所有字体。所以我假设使用 DT_CALCRECT
使用 DrawTextW
的返回值不提供任何附加值.
对于我机器上的所有字体,这些都是正确的:
HeightChinese == HeightLatin
LOGFONTW.lfHeight == TEXTMETRICW.tmHeight
(1).对于我机器上的大多数字体,这是正确的:
HeightXxx == 2 * TEXTMETRICW.tmHeight
这已经与另一个问题中提供的公式相矛盾(TEXTMETRICW.tmExternalLeading
不起作用)。
例如,“宋体”与 LOGFONTW.lfHeight = 36
会有TEXTMETRICW.tmExternalLeading = 1
, 和 HeightXxx == 72
(不是 74)。截屏和测量像素点的线距也是72(看来返回值是可信的)。
同时,“Segoe UI”与LOGFONTW.lHeight = 43
会有TEXTMETRICW.tmExternalLeading = 0
, 和 HeightXxx == 84
(不是 86)。
这是我系统上所有异常字体的列表:
"FontName" -- "DrawText return value" vs "2 * TEXTMETRICW.tmHeight"
Ebrima -- 84 vs 86
Leelawadee UI -- 84 vs 86
Leelawadee UI Semilight -- 84 vs 86
Lucida Sans Unicode -- 96 vs 98
Malgun Gothic -- 84 vs 86
Malgun Gothic Semilight -- 84 vs 86
Microsoft Tai Le -- 80 vs 82
Microsoft YaHei -- 82 vs 84
Microsoft YaHei UI Light -- 82 vs 84
MS Gothic -- 66 vs 64
MS UI Gothic -- 66 vs 64
MS PGothic -- 66 vs 64
Nirmala UI -- 84 vs 86
Nirmala UI Semilight -- 84 vs 86
Palatino Linotype -- 84 vs 86
Segoe UI -- 84 vs 86
Segoe UI Black -- 84 vs 86
Segoe UI Historic -- 84 vs 86
Segoe UI Light -- 84 vs 86
Segoe UI Semibold -- 84 vs 86
Segoe UI Semilight -- 84 vs 86
Segoe UI Symbol -- 84 vs 86
SimSun -- 66 vs 64
NSimSun -- 66 vs 64
SimSun-ExtB -- 66 vs 64
Verdana -- 76 vs 78
Webdings -- 62 vs 64
Yu Gothic UI -- 84 vs 86
Yu Gothic UI Semibold -- 84 vs 86
Yu Gothic UI Light -- 84 vs 86
Yu Gothic UI Semilight -- 84 vs 86
MS Mincho -- 66 vs 64
MS PMincho -- 66 vs 64
Ubuntu Mono -- 62 vs 64
有时返回值比计算值大2,有时比计算值小2。
我查看了 TEXTMETRICW
中的其他值,我还查看了可用的额外数据 int OUTLINETEXTMETRICW
,但我找不到任何可以解释观察结果的模式。
那么,计算行高的正确指标是什么?我知道我可以调用 DrawTextW
与 DT_CALCRECT
获取此值,但我想了解此信息的来源(以及字体设计师如何以可预测的方式控制它)。
Here is a gist with a complete Windows application that demonstrates this .所有有趣的东西都在 WM_PAINT
中.搜索 @EDIT
对于一些有趣的代码开关和断点。 在发布此问题时,我的 GitHub 帐户已被标记,Gist 暂时不可用。希望这件事能尽快解决。
(1) 我正在使用 EnumFontFamiliesEx
枚举所有字体,它恰好提供了LOGFONTW
具有正的结构lfHeight
值。这意味着我使用的是单元格高度,而不是字符高度。虽然 字符高度 是更典型的指定字体高度的方式,但这在这里有点无关紧要,单元格高度 恰好等于 TEXTMETRICW.tmHeight
。 ,但字符高度不是。计算的相关值为TEXTMETRICW.tmHeight
,而不是 LOGFONTW.lfHeight
.
最佳答案
正如 Jonathan Potter 指出的那样,公式 TEXTMETRICW.tmHeight
应该 是正确的,如果设置了 DT_EXTERNALLEADING
标志,那么它是TEXTMETRICW.tmHeight + TEXTMETRICW.tmExternalLeading
。
我用 Ghidra 对 DrawTextExW
进行了逆向工程,数字有时不对的原因不是 DrawTextExW
本身。 DrawTextExW
内部使用了一个DT_InitDrawTextInfo
,它又使用了GetTextMetricsW
并根据上述公式计算行高。
但是,请考虑使用此代码来探测所有字体:
LOGFONTW Probe = {};
Probe.lfCharSet = DEFAULT_CHARSET;
EnumFontFamiliesExW(hdc, &Probe, InitializeFontInfo_EnumFontFamiliesCallback, NULL, 0);
static int CALLBACK InitializeFontInfo_EnumFontFamiliesCallback(const LOGFONTW *LogFont, const TEXTMETRICW *TextMetric, DWORD FontType, LPARAM lParam)
{
FONT_INFO tmp = {};
tmp.LogFont = *LogFont;
tmp.TextMetric = *TextMetric;
FontInfo.push_back(tmp);
return 1;
}
这里以Segoe UI字体为例,LogFont->lfHeight
将为43。
因此,TextMetric->tmHeight
也将为 43,您会认为这在某种程度上是有意义的。
但是:
如果您继续将此 LogFont
选择到 HDC
中,然后使用 GetTextMetricsW
,如下所示:
HFONT Font = CreateFontIndirectW(LogFont);
SelectObject(hdc, Font);
TEXTMETRICW TextMetric = {};
GetTextMetricsW(hdc, &TextMetric);
然后 TextMetric->tmHeight == 42
即使 LogFont->lfHeight == 43
。
换句话说,为 EnumFontFamiliesExW
回调提供的 TEXTMETRICW
参数的值不可信。尽管您可能会争辩说错误出在其他地方,并且选择 LogFont->lfHeight == 43
字体实际上也应该产生 TextMetric->tmHeight == 43
文本规范,但我想这要求太多了。我的猜测是其中某处正在进行浮点转换,并且偶尔会对某些数字产生舍入误差。
关于windows - 获取 DrawText [Ex] 解释的 GDI HFONT 行高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66186989/
我使用 Win32 API 和 C/C++。我有一个 HFONT,想用它来创建一个新的 HFONT。新字体应该使用完全相同的字体规范,只是它应该是粗体。比如: HFONT CreateBoldFont
我在这里使用原始的 Windows API。我试图在 WM_INITDIALOG 消息期间将字体传递给对话框,然后在该对话框内创建新的子窗口时继续使用该字体。但我不想继续传递我创建的 HFONT,我想
我遇到过这样一种情况,我们需要知道 QFont 当前使用的字体的文件名。 .知道一个QFont可以给我们字体系列和 Windows HFONT处理。 字体系列是不够的,因为像Bold这样的操作样式或
我正在为使用 MFC 构建并使用普通旧 GDI 的旧应用程序添加 SVG 导出支持。由于 SVG 1.1 不支持文本换行,我不得不手动执行此操作。 该应用程序为我提供了一个CFont 实例(其中包含一
这个问题在这里已经有了答案: Create modified HFONT from HFONT (2 个答案) What are the windows system font specificat
HFONT childfont = SendMessage (childwin, WM_GETFONT, NULL, NULL); 导致错误“从‘LRESULT’到‘HFONT__*’的无效转换”当M
在我的对话框中,我将字体设置为默认的 GUI 字体,但是我确实需要手动将字体大小设置为 15。我该怎么做? HFONT myQueryFont; myQueryFont = (HFONT)GetS
我想知道哪些指标用于计算正确的行高(2 个相邻文本行基线之间的垂直距离)。 “正确”应任意定义为“无论 DrawTextW 做什么”。 The accepted answer here似乎遵循图表提供
我是一名优秀的程序员,十分优秀!