Почему некоторые программы плохо работают на разных экранах, а некоторые нет
Современные приложения Windows должны включать манифест, который представляет собой XML-документ, который обычно внедряется в основной EXE-файл. В манифестах объявляется несколько важных вещей, в том числе о том, будет ли программа запрашивать повышение уровня UAC, и, что более важно, уровень осведомленности о DPI. Если программа понимает, как перерисовать себя для различных настроек точек на дюйм, она поддерживает DPI.
В этой статье «Старая новая вещь» упоминаются три уровня осведомленности о DPI, доступные в Windows 8.1 и более поздних версиях: отсутствие осведомленности (в этом случае система будет увеличивать масштаб программы, создавая размытость), осведомленность о системном DPI и осведомленность о DPI для каждого монитора. Разница между этими двумя последними заключается в том, что программы, поддерживающие каждый монитор-DPI, должны перерисовывать себя в зависимости от того, на каком мониторе они находятся, поскольку разные мониторы могут иметь разные DPI. Программы, поддерживающие систему DPI, масштабируют себя для монитора с самым высоким разрешением, а затем система масштабирует их соответствующим образом.
Я проверил манифесты упомянутых вами программ, выполнив поиск в шестнадцатеричном редакторе строки <dpiAware
. Вот мои результаты:
- Internet Explorer 11:
True/PM
(для каждого монитора)
- Microsoft Word 2016:
True
(с учетом системы)
- Adobe Reader XI:
True/PM
Таким образом, Word частично обрабатывается системой, что объясняет, почему он работает так, как вы ожидаете. Другие программы должны обрабатывать себя, но, очевидно, они испортили. Программы с поддержкой DPI-монитора получают информацию об изменении монитора с помощью сообщения окна WM_DPICHANGED
, но, по-видимому, в ответ на это они поступают неправильно.
Дополнительная информация: Написание DPI-Aware Desktop и приложений Win32
Как это исправить
Можно использовать инфраструктуру совместимости, чтобы вызвать размытость (то есть сделать программы не поддерживающими DPI вообще), но кажется, что вы хотите сделать эти программы только частично осведомленными о DPI (т.е. использовать системный уровень). Единственный способ, которым я могу придумать, - это ударить EXE с помощью шестнадцатеричного редактора и изменить манифест. Мне нравится XVI32, нет принадлежности.
Запустите ваш редактор hex в качестве администратора и откройте файл программы, который вы хотите изменить. Ищите <dpiAware
, затем читайте немного вперед, пока не найдете True/PM
(или другую заглавную букву ). Скорее всего, сразу за ним следует закрывающий тег </dpiAware>
, поэтому мы напишем над ним так:
Old: True/PM</dpiAware>
New: True</dpiAware>
Не забудьте перезаписать лишний пробел (re>
) пробелами. Возможно, вам придется изменить права доступа к файлу перед сохранением. Как только файл будет изменен, это будет только программа с поддержкой DPI.
Похоже, что сборка Internet Explorer, которая поставляется с Windows 10, использует SetProcessDpiAwareness
а не манифест для настройки осведомленности о DPI. Поэтому нам нужно немного серьезнее отнестись к шестнадцатеричному редактированию. Найдите windowsSettings
, затем переместите курсор сразу после закрывающей скобки предыдущего тега application
. Перезаписать все это:
<windowsSettings><dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware></windowsSettings></application><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><!--
Как только вы закончите, это должно выглядеть следующим образом (я выделил новую часть красным цветом и поместил синий курсор в начало измененной части):
Это использует дополнительные пробелы и комментарии в манифесте по умолчанию, чтобы вставить наш новый параметр и немного продвинуть элемент compatibility
. Когда dpiAwareness
установлен в манифесте, функция SetProcessDpiAwareness
не будет иметь никакого эффекта.
Существует вероятность, что Windows Resource Protection откатит изменения, поэтому, если программа автоматически вернется, вам может потребоваться настроить сценарий для повторного копирования новой версии поверх него.
Внимание! Очень важно перезаписывать, а не вставлять или удалять символы. Вставка или удаление будут сдвигать остальные исполняемые данные, ломая много вещей. Если вы допустили ошибку транскрипции, не нажимайте клавишу Backspace или Delete. Вместо этого переместите курсор назад и замените свою ошибку правильными символами. Если вы ранее не использовали шестнадцатеричный редактор, сделайте резервную копию EXE-файла перед его изменением.