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

时间:2011-05-19 10:30:33

标签: windows visual-studio visual-studio-2008 winapi mfc

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

enter image description here

我已经创建了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"));

感谢您的帮助!

1 个答案:

答案 0 :(得分:83)

第一个示例是使用系统字体(SYSTEM_FONT),使用GetStockObject function检索,这是自Windows 3时代以来尚未使用的位图字体。有更多信息可用在Raymond Chen's blogMichael Kaplan's blog

第二个例子是使用"MS Shell Dlg" font,就像你问的那样。这实际上映射到一个名为“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标志,Raymond talks about here

在Windows Vista问世之前,一切都很好。而在Windows Vista中,微软的权力决定了Tahoma有点长牙,Windows应该是another UI font upgrade。他们在内部开发了自己的特殊字体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点这种事情确实让用户界面看起来没有修饰,而且在Vista的早期阶段就是大量挑剔的主题。现在,似乎大多数人已经忘记了它,但UI并没有开始寻找任何不那么分散和不一致。

你不是Windows shell团队:你无法在自己的应用程序中侥幸逃脱。 Top Rules for the Windows Vista User Experience偶然明确指出你应该总是:

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

说实话,我还没有真正听过这个问题的好的解决方案。而且我怀疑在我做的时候,没有人需要再支持Windows XP了(虽然大多数人相当那里尚未)。但这就是我的工作:我使用SystemParametersInfo function在运行时提取默认系统字体。幸运的是,无论当前版本的Windows和用户选择的主题如何,系统消息框字体(lfMessageFont)都是正确的字体和大小。

我初始化窗口或对话框的代码通常看起来像这样(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));

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

// 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。它使初始化代码 lot 更简单。