Не удается определить, изменился ли размер шрифта Windows на C ++ MFC

StackOverflow https://stackoverflow.com/questions/210646

Вопрос

Я пытаюсь определить, как я могу определить, когда пользователь изменяет размер шрифта Windows с обычного на очень крупный, размер шрифта выбирается путем выполнения следующих шагов на компьютере с Windows XP:

  1. Щелкните правой кнопкой мыши на рабочем столе и выберите пункт Свойства.
  2. Перейдите на вкладку Внешний вид.
  3. Выберите Размер шрифта:Обычные / Крупные Шрифты / Очень Крупные Шрифты

Насколько я понимаю, изменение размера шрифта приводит к изменению DPI, поэтому вот что я пробовал до сих пор.


Моя Цель:

Я хочу определить, когда Размер шрифта Windows изменился с обычного на крупный или сверхбольшой шрифт и выполните некоторые действия, основанные на этом изменении размера шрифта.Я предполагаю, что при изменении размера шрифта Windows изменится и DPI (особенно если размер шрифта очень большой


То, что я пробовал до сих пор:

Я получаю несколько сообщений, в том числе:WM_SETTINGCHANGE, WM_NCCALCSIZE, WM_NCPAINT и т.д...но ни одно из этих сообщений не является уникальным для ситуации, когда изменяется размер шрифта, другими словами, когда я получаю сообщение WM_SETTINGSCHANGE, я хочу знать, что изменилось.

Теоретически, когда я определяю OnSettingChange и Windows вызывает его, lpszSection должен сообщить мне, что представляет собой раздел изменения, и это работает нормально, но затем я проверяю данный раздел, вызывая SystemParametersInfo, и я передаю действие SPI_GETNONCLIENTMETRICS, и я прохожу через отладчик и убеждаюсь, что просматриваю данные в возвращенных НЕКЛИЕНТМЕТРИКАХ на предмет любых изменений шрифта, но ничего не происходит.

Даже если это не сработает, я все равно смогу проверить DPI при изменении настроек.Я действительно не заботился бы о других деталях, каждый раз, когда я получаю сообщение WM_SETTINGCHANGE, я бы просто проверял DPI и выполнял действия, которые мне интересны, но я также не могу получить системный DPI.

Я попытался получить DPI, вызвав метод GetSystemMetrics, также для каждого DC:

Dekstop DC->GetDeviceCaps LOGPIXELSX/LOGPIXELSY Оконный DC->GetDeviceCaps LOGPIXELSX/LOGPIXELSY Текущий постоянный ток->GetDeviceCaps LOGPIXELSX/LOGPIXELSY

Даже если я изменю DPI в окне графических свойств, эти значения не вернут ничего другого, они всегда показывают 96.

Кто-нибудь может помочь мне разобраться в этом, пожалуйста?Что я должен искать?На что мне следует обратить внимание?

afx_msg void CMainFrame::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
{
    int windowDPI = 0;
    int deviceDPI = 0;
    int systemDPI = 0;
    int desktopDPI = 0;
    int dpi_00_X = 0;
    int dpi_01_X = 0;
    int dpi_02_X = 0;
    int dpi_03_X = 0;

    CDC* windowDC = CWnd::GetWindowDC(); // try with window DC
    HDC desktop = ::GetDC(NULL); // try with desktop DC
    CDC* device = CWnd::GetDC(); // try with current DC
    HDC hDC = *device; // try with HDC
    if( windowDC )
    {
        windowDPI = windowDC->GetDeviceCaps(LOGPIXELSY); 
        // always 96 regardless if I change the Font 
        // Size to Extra Large Fonts or keep it at Normal

        dpi_00_X = windowDC->GetDeviceCaps(LOGPIXELSX); // 96
    }

    if( desktop )
    {
        desktopDPI = ::GetDeviceCaps(desktop, LOGPIXELSY); // 96
        dpi_01_X = ::GetDeviceCaps(desktop, LOGPIXELSX); // 96
    }

    if( device )
    {
        deviceDPI = device->GetDeviceCaps(LOGPIXELSY); // 96
        dpi_02_X = device->GetDeviceCaps(LOGPIXELSX); // 96
    }

    systemDPI = ::GetDeviceCaps(hDC, LOGPIXELSY); // 96
    dpi_03_X = ::GetDeviceCaps(hDC, LOGPIXELSX); // 96

    CWnd::ReleaseDC(device);
    CWnd::ReleaseDC(windowDC);
    ::ReleaseDC(NULL, desktop);
    ::ReleaseDC(NULL, hDC);

    CWnd::OnWinSettingChange(uFlags, lpszSection);
}

Значение DPI всегда возвращает 96, но изменения настроек вступают в силу, когда я меняю размер шрифта на очень крупные шрифты или если я меняю DPI на 120 (из свойств графики).

Это было полезно?

Решение

[РЕДАКТИРОВАТЬ после перечитывания] Я почти уверен, что переход на "Крупные шрифты" не приводит к изменению DPI, скорее это настройка темы.Вы должны быть в состоянии убедиться, применив изменение "Крупные шрифты", а затем открыв дополнительные свойства отображения, где задан параметр DPI, он должен был оставаться на уровне 96 точек на дюйм.


Предполагается, что для изменения DPI потребуется перезагрузка.Может быть, параметр не распространился на место, где GetDeviceCaps может его получить?

Возможно, попробуйте изменить параметр, не требующий перезагрузки (возможно, разрешение), а затем посмотрите, сможете ли вы обнаружить изменение.Если вы можете, ваш ответ, вероятно, заключается в том, что вы не можете обнаружить изменение DPI до окончания перезагрузки.

Другие советы

Когда вы вызываете GetDeviceCaps() на рабочем столе DC, возможно, вы используете DC, который может быть кэширован MFC и, следовательно, содержит устаревшую информацию?Выполняете ли вы синхронный вызов GetDeviceCaps() изнутри вашего обработчика OnSettingsChange?Я мог бы понять, как любая или обе эти вещи могут привести к тому, что вы получите устаревшую версию DPI.

Рэймонд Чен писал об этом и его решение выглядело примерно так (Обратите внимание, что я добавил ::операторы, позволяющие избежать вызова оболочек MFC API-интерфейсов):

int GetScreenDPI()
{
  HDC hdcScreen = ::GetDC(NULL);
  int iDPI = -1; // assume failure
  if (hdcScreen) {
    iDPI = ::GetDeviceCaps(hdcScreen, LOGPIXELSX);
    ::ReleaseDC(NULL, hdcScreen);
  }
  return iDPI;
}

У меня есть предчувствие, что WM_THEMECHANGED позаботится о тебе.Однако в нем нет никаких намеков на то, что изменилось.Вам придется использовать начальные настройки OpenThemeData и cache, а затем сравнивать каждый раз, когда вы получаете сообщение.

Вам, вероятно, не нужно заботиться о том, что изменилось, хотя, разве у вас не может быть процедуры компоновки общего назначения, которая настраивает вашу форму / диалоговое окно / что угодно, принимая все во внимание и предполагая, что вы начинаете с нуля?

Какую проблему вы пытаетесь решить?

Видишь http://msdn.microsoft.com/en-us/library/ms701681 (ПРОТИВ 85).aspx , это объясняется там (цитата:"Если вы не отмените масштабирование dpi, этот вызов вернет значение по умолчанию 96 dpi".)

Я не думаю, что разрешение дисплея меняется при изменении размера шрифта.Windows, вероятно, просто отправляет WM_PAINT и WM_NCPAINT сообщения отправляются во все открытые окна, и они перерисовываются, используя текущий (теперь крупный) системный шрифт.

Посмотрите на эти значения в Реестре:

Тема Windows XP HKCU\Программное обеспечение\Microsoft\Windows\CurrentVersion hemeManager\SizeName Возможные значения:NormalSize, LargeFonts и ExtraLargeFonts Эти значения являются не зависит от языка.

Классическая тема Windows HKCU \ Панель управления \ Внешний вид \ Текущий Возможные значения:Windows Classic, Windows Classic (большой), Windows Classic (очень большой), Windows Standard, Windows Standard (большой), Windows Standard (очень большой) Обратите внимание, что эти значения зависит от языка.

Windows Vista не поддерживает эту функцию.Если нам нужен шрифт большего размера, просто измените настройку DPI.В этом случае GetDeviceCaps должен работать.

Надеюсь, это поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top