哪种字体是 MFC 对话框控件的默认字体?

下图(放大,以便您更好地看到差异)显示了动态创建的编辑控件(上面的两个示例)和从对话框编辑器创建的编辑控件(下面的示例)之间的字体差异.如何使动态创建的 CEdit 控件的字体看起来像默认的(下例)?

The picture below (enlarged, so you better see the differences) shows Font differences between dynamically created Edit controls (the upper two examples) and Edit Controls created from the Dialog Editor (the lower example). How can I make the font of my dynamically created CEdit controls looking like the default (the lower example)?

我创建了 CEdit 控件,如下所示:

I have created the CEdit Controls like following:

obj->CreateEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T(""),
              WS_CHILD | WS_VISIBLE | WS_TABSTOP,
              rect.left, rect.top, rect.Width(), rect.Height(),
              GetSafeHwnd(), reinterpret_cast<HMENU>(mId));

obj->SetFont(&mFont); // mFont was created in the Dialog Constructor
                      // with mFont.CreatePointFont(80, _T("MS Shell Dlg"));

感谢您的帮助!

推荐答案

第一个示例是使用系统字体 (SYSTEM_FONT),通过 GetStockObject 函数,这是一种位图字体自 Windows 3 以来就没有使用过.更多信息可在 RaymondChen 的博客,以及 Michael Kaplan 的博客.

The first example is using the System font (SYSTEM_FONT), as retrieved with the GetStockObject function, which is a bitmap font that has not been used since the days of Windows 3. More information is available on Raymond Chen's blog, and Michael Kaplan's blog.

第二个例子是使用 "MS Shell Dlg" 字体,就像您要求的那样.这实际上映射到一种名为Microsoft Sans Serif"或MS Sans Serif"的字体,这是 Windows 95 和 98 时代的 UI 字体.这也称为 DEFAULT_GUI_FONT,它确实用于为它取一个准确的名字,但唉,它不再准确了.

The second example is using the "MS Shell Dlg" font, just like you asked it to. That actually maps to a font called "Microsoft Sans Serif" or "MS Sans Serif", the UI font back in the days of Windows 95 and 98. This is also known as DEFAULT_GUI_FONT, which indeed used to be an accurate name for it, but alas, it is accurate no longer.

从 Windows 2000 开始(并在 XP 中继续),Tahoma 被用作默认的 UI 字体.这就是您在第三个示例中看到的:Tahoma 8 pt.不幸的是,即使在这些操作系统上,MS Shell Dlg"也不返回 Tahoma――它仍然返回 MS Sans Serif,这就是它看起来错误的原因.

Beginning with Windows 2000 (and continued in XP), Tahoma was used as the default UI font. This is what you are seeing in the third example: Tahoma 8 pt. Unfortunately, even on those operating systems, "MS Shell Dlg" does not return Tahoma--it still returns MS Sans Serif, which is why it looks wrong.

因此,您可以简单地将 Tahoma 指定为 GUI 字体,但这实际上并不正确,因为它会在未安装或支持 Tahoma 的旧版操作系统或外语版本的操作系统中中断操作系统,其中出于需要使用不同的字体.相反,您应该指定 DS_SHELLFONT 标志,该标志 雷蒙德在这里谈论.

So, you could simply specify Tahoma as the GUI font, but that wouldn't really be correct, because it would break in older versions of the OS where Tahoma isn't installed or supported, or on foreign language versions of the operating system, where a different font is used out of necessity. Instead, you're supposed to specify the DS_SHELLFONT flag, which Raymond talks about here.

在 Windows Vista 出现之前,一切都很好.在 Windows Vista 中,Microsoft 的权力决定 Tahoma 有点老了,而 Windows 应该是 另一个 UI 字体升级.他们在内部开发了自己的特殊字体,称为 Segoe UI,据称专为优化屏幕显示而设计可读性.在一个特别的小变化中,他们决定默认大小现在应该是 9 pt,而不是每个以前版本的操作系统使用的 8 pt,无论字体如何.而且您可能认为MS Shell Dlg"、MS Shell Dlg2"或DS_SHELLFONT(或所有三个)都会为您提供这种新颖的 Segoe UI 字体,但你错了.

And all was fine and good until Windows Vista came out. And in Windows Vista, the powers that be at Microsoft decided that Tahoma was getting a little long-in-the-tooth and Windows was due for another UI font upgrade. They developed their own special font in-house called Segoe UI, supposedly designed for optimum on-screen readability. And in a special little twist, they decided that the default size should now be 9 pt, instead of 8 pt as used by every previous version of the OS, regardless of the font face. And you would probably think that either "MS Shell Dlg", "MS Shell Dlg2", or DS_SHELLFONT (or all three) would get you this new-fangled Segoe UI font, but you'd be wrong.

哦哦.现在事情变得棘手了……Vis??ta 不仅使用了与 XP 不同的字体,这种字体不容易通过通用标识符访问,而且它还使用了不同的大小,从而改变了你的对话框在这些系统上的显示方式,如果你能让它显示的话.在很多很多地方,Windows shell 团队似乎只是简单地放弃了挑战――Tahoma 8 pt 被到处使用,即使启用了 Aero 主题,当它应该使用 Segoe UI 时9 点这种东西确实让 UI 看起来很粗糙,而且在 Vista 的早期,它是很多吹毛求疵的主题.现在,似乎大多数人已经忘记了它,但 UI 并没有开始变得不那么分散和不一致.

Uh oh. Now things get tricky... Not only does Vista use a different font than XP that is not easily accessible with a one-size-fits-all identifier, but it also uses a different size, changing the way your dialog will look on those systems, if you can get it to display at all. In many, many places, the Windows shell team appeared to simply punt the challenge--Tahoma 8 pt is used all over the place, even with the Aero theme enabled, when it's supposed to be using Segoe UI 9 pt. This kind of thing really makes the UI look unpolished, and it was the subject of lots of nitpicking back in the early days of Vista. Now, it seems most people have forgotten about it, but the UI hasn't started looking any less scattered and inconsistent.

而且您不是 Windows shell 团队:您无法在自己的应用程序中摆脱这种情况.TopWindows Vista 用户体验规则甚至明确指出您应该始终:

And you're not the Windows shell team: you can't get away with this in your own app. The Top Rules for the Windows Vista User Experience even state explicitly that you should always:

  • 使用新的 Windows Vista 系统字体 Segoe UI.
  • 通过始终使用 Windows 主题 API 引用系统字体、大小和颜色来尊重用户的设置.不要对字体、大小或颜色使用固定值.

老实说,我还没有真正听说过这个问题的好的解决方案.而且我怀疑到我这样做的时候,没有人将需要支持 Windows XP(尽管大多数人还没有完全).但这是我所做的:我在运行时使用 SystemParametersInfo 函数.幸运的是,无论当前版本的 Windows 和用户选择的主题如何,系统消息框字体 (lfMessageFont) 都是正确的字体和大小.

To be honest, I haven't really heard a good solution to this problem yet. And I suspect that by the time I ever do, no one will need to support Windows XP anymore (although most people aren't quite there yet). But here's what I do: I extract the default system font at runtime using the SystemParametersInfo function. Fortunately, the system message box font (lfMessageFont) is the correct font face and size, regardless of the current version of Windows and the user's chosen theme.

我的初始化窗口或对话框的代码通常看起来像这样(SystemInfo::IsVistaOrLater 是我编写的辅助函数;实现是显而易见的):

My code to initialize windows or dialogs generally looks something like this (SystemInfo::IsVistaOrLater is a helper function I've written; the implementation is the obvious):

// Get the system message box font
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(ncm);

// If we're compiling with the Vista SDK or later, the NONCLIENTMETRICS struct
// will be the wrong size for previous versions, so we need to adjust it.
#if(_MSC_VER >= 1500 && WINVER >= 0x0600)
if (!SystemInfo::IsVistaOrLater())
{
    // In versions of Windows prior to Vista, the iPaddedBorderWidth member
    // is not present, so we need to subtract its size from cbSize.
    ncm.cbSize -= sizeof(ncm.iPaddedBorderWidth);
}
#endif

SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
HFONT hDlgFont = CreateFontIndirect(&(ncm.lfMessageFont));

// Set the dialog to use the system message box font
SetFont(m_DlgFont, TRUE);
SendMessage(hWnd, WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(FALSE, 0));

或者在 MFC 中更容易,使用方便的 SendMessageToDescendants 方法
(m_DlgFont 是为类定义的 CFont 对象):

Or even easier in MFC, with the handy SendMessageToDescendants method
(m_DlgFont is a CFont object defined for the class):

// Get the system message box font
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
LOGFONT lfDlgFont = ncm.lfMessageFont;
m_DlgFont.CreateFontIndirect(&lfDlgFont);

// Set the dialog and all its controls to use the system message box font
SetFont(m_DlgFont, TRUE);
SendMessageToDescendants(WM_SETFONT, (WPARAM)m_DlgFont.m_hFont, MAKELPARAM(FALSE, 0), TRUE);

如果您不使用 MFC,我强烈建议您实现您自己的 SendMessageToDescendants 递归版本.它使初始化代码很多更简单.

If you're not using MFC, I highly recommend implementing your own recursive version of SendMessageToDescendants. It makes the initialization code a lot simpler.

相关文章