程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了获取 DrawText[Ex]大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决获取 DrawText[Ex]?

开发过程中遇到获取 DrawText[Ex]的问题如何解决?下面主要结合日常开发的经验,给出你关于获取 DrawText[Ex]的解决方法建议,希望对你解决获取 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>

一个观察结果是,对于我机器上的所有字体,如果使用了 DrawTextWRECT 的返回值将始终与 DT_CALCRECT 输出匹配。因此,我假设使用 DT_CALCRECT 不会比使用 DrawTextW 的返回值提供任何额外的价值。

对于我机器上的所有字体,这些都是正确的

  • HeightChinese == HeightLaTin
  • LOGFontW.lfheight == TEXTMETRICW.tmHeight (1).

对于我机器上的大多数字体,这是真的:

  • HeightXxx == 2 * TEXTMETRICW.tmHeight

这已经与另一个问题中提供的公式相矛盾了TEXTMETRICW.tmExternalLeading 不起作用)。

例如,带有 LOGFontW.lfheight = 36 的“Arial”将具有 TEXTMETRICW.tmExternalLeading = 1HeightXxx == 72(不是 74)。截屏和测量像素时的行距也是72(这样看来返回值是可信的)。

同时,带有 LOGFontW.lHeight = 43 的“Segoe UI”将具有 TEXTMETRICW.tmExternalLeading = 0HeightXxx == 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,您会认为这在某种程度上是有意义的。

但是:

如果您继续选择此 LogFontHDC 中,然后使用 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,请注明来意。
标签:获取