DLGTEMPLATEEX和DS_SHELLFONT:点大小怎么样?

时间:2017-01-03 16:44:55

标签: winapi

我正在使用DLGTEMPLATEEX结构在内存中手动创建对话框。我总是希望对话框控件使用默认的Shell字体,所以我设置DS_SHELLFONTMSDN says如果设置了DS_SHELLFONT,则“系统会使用pointsizeweightitalic成员中指定的字体数据选择字体”。 MSDN还说,如果我设置typeface,我必须将DS_SHELLFONT设置为“MS Shell Dlg”。 Raymond Chen says这种明显的冗余是由于兼容性原因造成的。

所以这对我来说一切都很好,但有一件事令我困惑:为什么我也要设置pointsize?这不是以某种方式与使用默认Shell字体和大小的系统的整个想法相矛盾吗?我的应用程序现在是DPI aware,我认为在DPI高于96的系统上,Shell字体也会更大。因此,在pointsize中对特定字体大小进行硬编码对我来说根本没有意义。

那么在设置pointsize时,有DS_SHELLFONT的重点是什么?我该怎么办?我应该只将pointsize设置为0吗?但MSDN并没有说它可以设置为0.它看起来好像我需要在这里传递一个特定的字体大小,但这似乎与整个DS_SHELLFONT想法相矛盾,或者我得到的东西错了吗?

1 个答案:

答案 0 :(得分:1)

TL;DR 您问题的直接答案是 8

善意的答案是使用 NONCLIENTMETRICS.lfMessageFont,并且不要改变它的任何内容(除了 DPI 缩放 lfHeight }},如果您决定自己这样做而不是使用 SystemParametersInfoForDpi)。

TL;DR 结束。

问得好。你问这个:“默认字体”的磅值是多少。嗯,默认字体可能有多种可能的定义(我目前正在研究在其他地方发布关于该问题的很长的答案,并偶然发现了这个问题),您选择的定义是“DS_SHELLFONT 定义”。

好的,那么问题就变成了,在对话框模板中,FONT 语句中的点大小是多少(无论对话框是使用 .rc 文件还是代码构建的,都是相同的概念)

STYLE DS_SHELLFONT | ...
FONT <WHAT GOES HERE?>, "MS Shell Dlg", 0, 0, 0x1
[...]

以下是您需要了解的一些事项:

  • 没有好的答案,因为微软搞砸了。
  • DS_SHELLFONT 导致 MS Shell Dlg 在创建对话框时被 MS Shell Dlg 2 替换。
  • MS Shell Dlg 2 在注册表中使用 Tahoma 映射到 FontSubstitutes,无论区域设置如何。它的整个存在都是如此,而且可能永远不会改变,至少在可预见的未来不会改变。
  • 其他人都使用 8,因为它是 Visual Studio 中的默认值。
  • Windows 内置对话框不使用 DS_SHELLFONT。对于每个语言环境,它们使用适合该语言环境的特定字体和字体大小,并在语言环境的 MUI 资源文件中进行硬编码。对于西方系统,字体为 MS Shell Dlg 8pt。这可能会给您一种错误的印象,即 MS Shell Dlg 是普遍适用的(因为它是注册表映射的伪字体),并且您可以在国际上以 8pt 的固定大小分发使用它的程序。但不是。例如,在日语系统上,它是 MS UI Gothic, 9pt。如果您在这里使用了 MS Shell Dlg 8pt,它将被替换为 MS UI Gothic 8pt,这对于日语文本来说太小了。确切的细节更复杂,超出了本答案的范围。所以基本上 MS Shell Dlg,硬编码在 8pt without DS_SHELLFONT 是一个错误。
  • WinForms 应用程序 (.NET Framework <= 4.8) 使用 GetStockObject(DEFAULT_GUI_FONT)。 .NET >= 5 使用 NONCLIENTMETRICSW.lfMessageFont。因此,如果您想让自己的东西融入这里,那么 DS_SHELLFONT 都不是您要走的路。

原则上,MS Shell Dlg 2MS Shell Dlg 有相同的问题,理论上它可以映射到一种字体,需要不同大小才能正确显示。但是因为 MS Shell Dlg 2 可能总是 Tahoma,并且因为基本上每个在 Visual Studio 中使用对话框编辑器创建的对话框默认大小为 8,所以最有可能假设 Microsoft 永远不会破坏它。所以你想放在那里的字体是 MS Shell Dlg, 8pt,而 DS_SHELLFONT 会将它有效地转换为 Tahoma 8pt。该 8 几乎在每个人的对话模板中都是硬编码的。

“微软搞砸了”是什么意思?好吧,我们不应该处于这种复杂的情况。基本上,通过使用像 MS Shell Dlg 2 这样的动态伪字体,您是在说 我现在已经完全准备好让默认字体随时更改,如果确实如此,我仍然会融入所有使用正确默认值的酷孩子!但事实是,您没有使用任何类似默认字体的东西。您只使用了一些默认的字体。如果某些 Windows GUI 设计人员确实决定是时候更改所有应用程序的默认字体,那么他们还可以控制字体大小、粗细和样式就很重要。当前的系统不允许这样做。字体很挑剔,例如,Segoe UI 9pt 的单个字符看起来更像典型的 8pt 字体(Segoe UI 在 8pt 时几乎不可读)。更不用说它无论如何都行不通,因为他们自己为特定语言环境硬编码了特定字体。

(巧合的是,这也是 CSS 中的一个巨大错误,它允许您定义后备字体,但不能定义后备字体大小。)

这就是为什么现在到处都推荐 NONCLIENTMETRICSW.lfMessageFont 的原因。它确实实现了假设的 Microsoft GUI 设计者想要的功能。而且您不必猜测正确的字体大小、粗细和样式是什么。

最后一点:如果您的程序根本没有本地化,那么硬编码一种在英语中看起来不错的具体字体可能是一个更好的主意。无论是Microsoft Sans Serif,还是Tahoma,还是Segoe UI。这使得布局更容易(您不必适应不同系统和用户设置等上最疯狂的字体度量差异)。并且它确保您漂亮的英文文本不会被中国 PC 上的默认字体完全污损