Не удается определить, когда размер шрифта Windows изменился C ++ MFC - PullRequest
7 голосов
/ 17 октября 2008

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

  1. Щелкните правой кнопкой мыши на рабочем столе и выберите «Свойства».
  2. Нажмите на вкладку «Внешний вид».
  3. Выберите размер шрифта: обычный / большой шрифт / очень большой шрифт

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


Моя цель:

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


Что я пробовал до сих пор:

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

Теоретически, когда я определяю OnSettingChange и Windows вызывает его, lpszSection должен сообщить мне, что такое изменяющийся раздел, и это работает нормально, но затем я проверяю данный раздел, вызывая SystemParametersInfo, и я передаю действие SPI_GETNONCLIENTMETRICS, и Я прохожу отладчик и проверяю данные в возвращенном NONCLIENTMETRICS на предмет любых изменений шрифта, но они не происходят.

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

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

Dekstop DC-> GetDeviceCaps LOGPIXELSX / LOGPIXELSY Окно DC-> GetDeviceCaps LOGPIXELSX / LOGPIXELSY Текущий DC-> 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, но изменения настроек ДЕЙСТВИТЕЛЬНО вступают в силу, когда я изменяю размер шрифта на Extra Large Fonts или если я меняю DPI на 120 (из графических свойств).

Ответы [ 6 ]

4 голосов
/ 17 октября 2008

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

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

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

2 голосов
/ 17 октября 2008

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

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

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

2 голосов
/ 17 октября 2008

Когда вы вызываете 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;
}
1 голос
/ 13 ноября 2008

См. http://msdn.microsoft.com/en-us/library/ms701681(VS.85).aspx, это объясняется там (цитата: «Если вы не отмените масштабирование точек на дюйм, этот вызов возвращает значение по умолчанию 96 точек на дюйм.»)

0 голосов
/ 27 июня 2009

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

Тема Windows XP HKCU \ Software \ Microsoft \ Windows \ CurrentVersion \ ThemeManager \ SizeName Возможные значения: NormalSize, LargeFonts и ExtraLargeFonts Эти значения не зависят от языка .

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

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

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

0 голосов
/ 17 октября 2008

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

...