下面的图片(放大,因此您最好看到差异)显示动态创建的编辑控件(上面的两个示例)和从对话框编辑器(下面的示例)创建的编辑控件之间的字体差异。如何使我动态创建的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"));
感谢您的帮助!
答案 0 :(得分:83)
第一个示例是使用系统字体(SYSTEM_FONT
),使用GetStockObject
function检索,这是自Windows 3时代以来尚未使用的位图字体。有更多信息可用在Raymond Chen's blog和Michael 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字体,但是你“这是错的。
你不是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 更简单。