Какой шрифт является стандартным для MFC Dialog Controls?

Рисунок ниже (увеличенный, чтобы вы лучше различили различия) показывает различия шрифта между динамически создаваемыми элементами управления Edit (два верхних примера) и Edit Controls, созданные из Редактора диалоговых окон (нижний пример). Как я могу сделать шрифт моих динамически созданных элементов управления 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

В первом примере используется системный шрифт (SYSTEM_FONT), полученный с помощью функции GetStockObject, которая является растровым шрифтом который не использовался со времен Windows 3. Дополнительная информация доступна на блог Raymond Chen и Блог Майкла Каплана.

Во втором примере используется шрифт "MS Shell Dlg" , как и вы его просили. Это фактически отображает шрифт под названием "Microsoft Sans Serif" или "MS Sans Serif", шрифт пользовательского интерфейса еще во времена Windows 95 и 98. Это также называется DEFAULT_GUI_FONT, который действительно был точным именем для это, но, увы, это уже не так.

Начиная с Windows 2000 (и продолжаясь в XP), Tahoma использовался как шрифт пользовательского интерфейса по умолчанию. Это то, что вы видите в третьем примере: Tahoma 8 pt. К сожалению, даже в этих операционных системах "MS Shell Dlg" не возвращает Tahoma - он по-прежнему возвращает MS Sans Serif, поэтому он выглядит неправильно.

Итак, вы можете просто указать Tahoma в качестве шрифта GUI, но это было бы неправильно, потому что оно сломалось бы в более старых версиях ОС, где Tahoma не установлена ​​или не поддерживается, или на языках иностранных языков операционной системы, где по необходимости используется другой шрифт. Вместо этого вы должны указать флаг DS_SHELLFONT, который Раймонд говорит здесь.

И все было хорошо и хорошо, пока Windows Vista не вышла. И в Windows Vista полномочия, которые были в Microsoft, решили, что Tahoma получает немного длинный зуб, и Windows должна была еще одна модернизация шрифта пользовательского интерфейса. Они разработали собственный специальный шрифт под названием Segoe UI, предположительно спроектированный для оптимальной читаемости на экране. И в особой небольшой завихренности они решили, что размер по умолчанию теперь должен быть 9 pt, вместо 8 pt, используемого каждой предыдущей версией ОС, независимо от лица шрифта. И вы, вероятно, подумали бы, что либо "MS Shell Dlg", "MS Shell Dlg2", либо DS_SHELLFONT (или все три) предоставят вам этот шрифт с новым шрифтом Segoe UI, но вы ошибаетесь.

О, о. Теперь все становится сложно... Не только Vista использует другой шрифт, чем XP, который нелегко доступен с идентификатором одного размера для всех, но он также использует другой размер, меняя как ваш диалог будет выглядеть в этих системах, если вы можете его отобразить вообще. Во многих и многих местах команда оболочки Windows, похоже, просто пыталась решить проблему - Tahoma 8 pt используется повсеместно, даже с включенной темой Aero, когда предполагается использовать Segoe UI 9 pt. Подобная вещь действительно делает пользовательский интерфейс неполированным, и это было предметом многократного поиска в первые дни Vista. Теперь, похоже, большинство людей забыли об этом, но пользовательский интерфейс не стал выглядеть менее рассеянным и непоследовательным.

И вы не команда оболочки Windows: вы не можете уйти от этого в своем приложении. Верхние правила для пользователя Windows Vista даже явно указывают, что вы всегда должны:

  • Используйте пользовательский интерфейс Segoe, новый системный шрифт Windows Vista.
  • Уважайте пользовательские настройки, всегда ссылаясь на системный шрифт, размеры и цвета с помощью API-интерфейсов Windows. Не используйте фиксированные значения для шрифтов, размеров или цветов.

Честно говоря, я пока не слышал хорошего решения этой проблемы. И я подозреваю, что к тому моменту, когда я когда-либо это сделаю, никто больше не будет нуждаться в поддержке Windows XP (хотя большинство людей еще не совсем там). Но вот что я делаю: я извлекаю системный шрифт по умолчанию во время выполнения с помощью SystemParametersInfo function. К счастью, шрифт окна системного сообщения (lfMessageFont) является правильным шрифтом и размером шрифта, независимо от текущей версии Windows и выбранной пользователем темы.

Мой код для инициализации окон или диалогов обычно выглядит примерно так (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));

Или еще проще в MFC, с удобным способом SendMessageToDescendants (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. Это делает код инициализации намного проще.