Программно определить настройки Windows DPI?

у нас возникла проблема с одним из наших приложений MFC, не поддерживающих dpi.
Если вы измените системные настройки на высокое разрешение (например, 120 или 144 dpi), значок приложения на панели задач будет выглядеть криво. К сожалению, нам нужно зарегистрировать собственный WNDCLASS для мейнфрейма, а в WNDCLASS.hIcon члене нужно установить иконку. Этот значок загружается с помощью функции LoadIcon. И эта функция пытается загрузить изображение в стандартном размере (такой же, как возвращаемый GetSystemMetrics(SM_CXICON)), который для 120 точек на дюйм составляет 40x40 пикселей. К сожалению, мы не предоставляем иконку такого размера. Но для этого есть обходной путь: поскольку, как ни странно, виртуализация точек на дюйм кажется неэффективной для 120 точек на дюйм, GetDeviceCaps(..., LOGPIXELSX) действительно возвращает 120 точек на дюйм, а GetSystemMetrics(SM_CXICON) возвращает 40. Таким образом, мы можем поймать это и просто загрузить значок другого размера. Но для 144 dpi это не работает, потому что сейчас вроде виртуализация действует, и мы получаем 96 dpi и 32 пикселя, из-за чего иконка опять выглядит очень некрасиво.
Я выяснил, что если просто поставить член WNDCLASS.hIcon к NULL, значок отображается нормально. Но мне интересно, нормально ли это, потому что, согласно MSDN:

hIcon
Описатель значка класса. Этот элемент должен быть дескриптором ресурса значка. Если этот элемент имеет значение NULL, система предоставляет значок по умолчанию.

Итак, могу ли я рассчитывать на то, что значок всегда будет отображаться, даже если я установлю для этого члена значение NULL? Другим способом было бы также загрузить значок правильного размера, но для этого мне нужно было бы знать, что система на самом деле настроена на 144 dpi. Вот мы и подошли к моему первоначальному вопросу. Кто-нибудь знает, можно ли определить настройку DPI системы (из виртуализированного приложения dpi)? Обратите внимание, что я также думал о том, чтобы сделать что-то грязное, например, чтобы приложение, поддерживающее dpi, сообщало мне фактическое dpi и тому подобное, но я хочу избежать таких вещей, если это возможно.

С наилучшими пожеланиями,

хамбагумба

Обновление:
я обнаружил, что установка члена WNDCLASS.hIcon на NULL не очень хорошая идея, потому что тогда значок мейнфрейма заменяется значком по умолчанию (хотя он выглядит нормально на панели задач ...) - Во время первого теста я этого не заметил.


person humbagumba    schedule 17.08.2010    source источник


Ответы (1)


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

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

Не исключено, что это вызовет несколько новых проблем. Все, что вы хотели бы знать об этом, очень хорошо освещено в этом Статья библиотеки MSDN.

person Hans Passant    schedule 17.08.2010
comment
Спасибо, но я уже был там. Это не совсем то, что я ищу, поскольку включение поддержки dpi вызывает слишком много проблем, особенно при 144 dpi. Знаете ли вы, почему приложения ведут себя так, как будто они поддерживают разрешение 120 точек на дюйм (например, без виртуализации и, следовательно, без масштабирования в стиле XP)? В статье также не упоминается, можно ли узнать, какова реальная настройка DPI в системе (без включения осведомленности о dpi). - person humbagumba; 17.08.2010
comment
Виртуализация DPI не срабатывает, пока DPI не превысит 120. Чтобы найти реальный DPI, необходимо отключить виртуализацию. - person Hans Passant; 17.08.2010