大佬教程收集整理的这篇文章主要介绍了获取 DrawText[Ex],大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我想知道使用哪些度量标准来计算正确的行高(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!",0);
预期的返回值应该是 2 * <SomethingUnkNown>
。
一个观察结果是,对于我机器上的所有字体,如果使用了 DrawTextW
,RECT
的返回值将始终与 DT_CALCRECT
输出匹配。因此,我假设使用 DT_CALCRECT
不会比使用 DrawTextW
的返回值提供任何额外的价值。
对于我机器上的所有字体,这些都是正确的:
对于我机器上的大多数字体,这是真的:
HeightXxx == 2 * TEXTMETRICW.tmHeight
这已经与另一个问题中提供的公式相矛盾了(TEXTMETRICW.tmExternalLeading
不起作用)。
例如,带有 LOGFontW.lfheight = 36
的“Arial”将具有 TEXTMETRICW.tmExternalLeading = 1
和 HeightXxx == 72
(不是 74)。截屏和测量像素时的行距也是72(这样看来返回值是可信的)。
同时,带有 LOGFontW.lHeight = 43
的“Segoe UI”将具有 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
结构提供了 positive { {1}} 个值。这意味着我使用的是单元格高度而不是字符高度。虽然字符高度是更典型的指定字体高度的方式,但在此与此无关,但碰巧单元格高度等于lfheight
,但字符高度不是。计算的相关值是 TEXTMETRICW.tmHeight
,而不是 TEXTMETRICW.tmHeight
。
DrawText()
仅在调用时设置了 TEXTMETRIC.tmExternalLeading
标志的情况下才使用 DT_EXTERNALLEADING
- 您似乎没有考虑到这一点。
行高公式基本上是:
int iLineHeight = tm.tmHeight + ((format & DT_EXTERNALLEADING) ? tm.tmExternalLeading : 0);
,
正如乔纳森·波特指出的那样,公式 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
文本度量,但我认为这要求太多了。我的猜测是那里的某个地方正在进行浮点转换,并且偶尔会产生一些数字的舍入错误。
以上是大佬教程为你收集整理的获取 DrawText[Ex]全部内容,希望文章能够帮你解决获取 DrawText[Ex]所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。