Какой шрифт используется по умолчанию для диалоговых элементов управления MFC? - PullRequest
40 голосов
/ 19 мая 2011

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

84 голосов
/ 19 мая 2011

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

Во втором примере используется шрифт 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 пт вместо 8 пт, используемых в каждой предыдущей версии ОС, независимо от шрифта.И вы бы , вероятно думали, что либо "MS Shell Dlg", "MS Shell Dlg2", либо DS_SHELLFONT (или все три) получат вам этот новомодный шрифт Segoe UI, но вы будетенеправильно.

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

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

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

Если честно, я пока не слышал хорошего решения этой проблемы.И я подозреваю, что к тому времени, когда я это сделаю, никому больше не нужно будет поддерживать Windows XP (хотя большинство людей еще не вполне пока ).Но вот что я делаю: я извлекаю системный шрифт по умолчанию во время выполнения, используя SystemParametersInfo функцию .К счастью, системный шрифт окна сообщения (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.Это упрощает код инициализации lot .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...