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

Chr*_*mer 43 windows winapi mfc visual-studio-2008 visual-studio

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

在此输入图像描述

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

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"));
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助!

Cod*_*ray 86

第一个例子是使用系统字体(SYSTEM_FONT),该GetStockObject函数是使用函数检索的,该函数是自Windows 3时代以来尚未使用的位图字体.更多信息可在Raymond Chen的博客Michael Kaplan的博客上获得.

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

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

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

在Windows Vista问世之前,一切都很好.而在Windows Vista中,微软的权力决定了Tahoma有点长,而Windows则需要进行另一次UI字体升级.他们在内部开发了自己的特殊字体Segoe UI,据说是为了获得最佳的屏幕可读性而设计的.并且在一个特别的小扭曲中,他们认为默认大小现在应该是9 pt,而不是每个以前版本的操作系统使用的8 pt,无论字体是什么.而且你可能认为"MS Shell Dlg","MS Shell Dlg2"或DS_SHELLFONT(或者全部三种)会让你获得这种新奇的Segoe UI字体,但你错了.

哦,哦.现在事情变得棘手...... Vista不仅使用了与XP不同的字体,而且使用一个通用的标识符也不容易访问,但它也使用不同的大小,改变了对话框在这些上看的方式系统,如果你可以让它显示.在很多很多地方,Windows shell团队似乎只是挑战了这个挑战 - 即使启用了Aero主题,Tahoma 8 pt也被用于所有地方,当它应该使用Segoe UI 9 pt时.这种事情确实让用户界面看起来没有修饰,而且在Vista的早期阶段就是大量挑剔的主题.现在,似乎大多数人已经忘记了它,但UI还没有开始寻找任何不那么分散和不一致的东西.

而且你不是Windows shell团队:你无法在自己的应用程序中侥幸逃脱.Windows Vista用户体验最高规则甚至明确规定您应始终:

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

说实话,我还没有真正找到解决这个问题的方法.我怀疑我通过曾经做的时候,没有人会需要支持Windows XP了(虽然大多数人都不是十分尚未).但这就是我所做的:我使用该SystemParametersInfo函数在运行时提取默认系统字体.幸运的lfMessageFont是,无论当前版本的Windows和用户选择的主题如何,系统消息框font()都是正确的字体和大小.

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

// 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));
Run Code Online (Sandbox Code Playgroud)

或者在MFC中更方便,使用方便的SendMessageToDescendants方法
(m_DlgFontCFont为类定义的对象):

// 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);
Run Code Online (Sandbox Code Playgroud)

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

  • @Christian:是的,你能看出我在这上面花了太多时间吗?支持您关心控件的外观并让它们适应平台的默认样式。很少有开发人员注意到这一点。事情可以追溯到比 Windows 3 更久远的时代;自 Windows 1.0 以来,Win32 API 的大部分内容都没有改变(至少在精神上)。向后兼容性是一个要求非常高的情妇。我所展示的代码(使用“SystemParametersInfo”和“NONCLIENTMETRICS.lfMessageFont”)返回*MS Sans Serif*的唯一方法是如果它被设置为您的Windows字体... (2认同)
  • @Christian:这一切都有道理,但你的结论不太正确。我是一个注重细节的人(以防你看不出来)。*默认*“Windows 经典”主题(称为“Windows 标准”)*实际上*使用 Tahoma 字体作为消息框字体。然而,*其他*预定义的配色方案则不然,因为它们自从在 Windows 95/98 中首次发布以来就没有更新过。但无论如何,如果 MS Sans Serif 是外观主题中的消息框字体,那么所有本机控件都将显示在该字体中。如果您想匹配它们,则也必须使用它。 (2认同)