Да здравствует мыло душистое, или как исправить неправильное масштабирование Windows программ

    Не секрет, что внедрение высокого разрешения экранов идет быстрее, чем адаптация Windows программ под них. Проблемы появляются в первую очередь тогда, когда нам надоедает напрягать глаза и пользоваться увеличительными стеклами, и мы изменяем масштабирование системы. Программы можно разделить на три категории по тому, как они ведут себя при этом:
    • Все элементы программы масштабируются правильно
    • Только некоторые элементы масштабируются правильно
    • Программа говорит Windows, что не умеет масштабироваться, и тогда операционная система сама масштабирует всю программу как умеет (в результате чего мы и видим замыленный интерфейс во многих старых программах)

    Самый неприятный вариант для пользователя — это конечно же второй. Он может не только сделать программу неудобной для использования, но и вообще сделать пользование невозможным.
    Ниже я покажу на примере QTIPlot как это можно исправить.

    QTIPlot — это программа, главная функция которой (как ясно из названия) — это построение графиков. Также она использует Qt, который и говорит операционной системе, что умеет сам масштабировать. Но к сожалению что-то идет не так и в результате графики, созданные и старательно выравненные на системе с масштабированием, теряют всю свою гармонию если их открыть на системе без масштабирования — шрифты начинают расползаться и т.п. Программа эта вроде как open source (хотя и надо обладать некоторыми детективными навыками, чтобы найти ее код), но с наскока мне исправить ее не удалось. Поэтому я расценил, что лучше жить с замыленным интерфейсом, чем искать замену программе, и решил заставить программу говорить Windows, что она не умеет масштабироваться.

    Для этого надо создать манифест-файл в той директории, где находится exe-файл, который мы хотим изменить, со следующим содержанием:
    qtiplot.exe.manifest
    <?xml version="1.0" encoding="utf-8"?>
    <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"
            xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
            xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
            xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
            <security>
                <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                    <requestedExecutionLevel level="asInvoker"
                    uiAccess="false" />
                </requestedPrivileges>
                <applicationRequestMinimum>
                    <defaultAssemblyRequest permissionSetReference="Custom" />
                    <PermissionSet class="System.Security.PermissionSet"
                    version="1" ID="Custom" SameSite="site" />
                </applicationRequestMinimum>
            </security>
        </trustInfo>
        <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
            <application>
            </application>
        </compatibility>
        <asmv3:application>
            <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <dpiAware>false</dpiAware>
            </asmv3:windowsSettings>
        </asmv3:application>
    </asmv1:assembly>
    


    (главное для нас здесь — это конечно же
    <dpiAware>false</dpiAware>
    
    ).
    После этого надо запустить «Developer Command Prompt» из Visual Studio Tools, перейти в эту директорию и выполнить команду
    mt.exe -nologo -manifest qtiplot.exe.manifest -outputresource:qtiplot.exe
    

    (естественно «qtiplot.exe» надо заменить на название того exe-файла, который надо пропатчить).
    Вот и всё, можно запускать программу и радоваться теплому замыленному интерфейсу с правильным масштабированием.


    Приятный бонус этих танцев с манифестом в том, что так можно исправить даже те программы, к которым у нас нет source кода.

    PS После того как написал эту публикацию, заметил, что слово «скалирование» не входит в современные орфографические словари. Пришлось заменить его везде на «масштабирование». По этому поводу ниже опрос.

    Only registered users can participate in poll. Log in, please.

    Каким бы словом вы назвали процесс изменения размеров с сохранением пропорций?

    Share post

    Similar posts

    Comments 45

      +9
      На этом фоне «порадовал» последний инсталлятор скайпа, у которого флажок «Intall Bing» прятался за картинкой, при этом был по умолчанию установлен. Надеюсь, тем кто не тестит инсталляторы, уготован отдельный пентиум-2 в аду.
        +2
        Вы уверены, что это ошибка?
          +2
          Есть, кстати, неплохая программа Unchecky. Сидит в процессах и отжимает галочки по установке тулбаров, поисковых движков и т.д. Ставлю всем, кому приходится помогать с настройкой компа — 1 мб оперативки того стоит — никакого побочного хлама больше не устанавливается.
          В случае со скайпом — особенно актуально.
            +6
            Было бы забавно, если у нее тоже были галочки при установке :)
            • UFO just landed and posted this here
            +8
            Слово «скалирование» вижу в первый раз.
            Английское обычно записывается «без модификаций» — «скейлинг»
              –4
              судя по опросу «скалирование» действительно не пользуется популярностью. Видать это и впрямь не русский язык :) Хотя в гугле это слово встречается. Вот бы была возможность привязывать голоса в опросе к данным из профиля — можно бы было посмотреть на корреляцию с географическим положением или профессией…
                +2
                Ещё бывает такой вариант, как «шкалирование». Хотя это уже скорее из области матстатистики. «Масштабирование» — уже достаточно заимствованное слово (звучит на немецкий лад).
                –4
                Слово «скейлинг» я бы и не понял, если б не контекст статьи, а «скалирование» — нормально и сразу понятно, о чём речь.
                «Масштабирование» — сначала подумал, что это zoom, как в браузере, когда крутишь колёсико мыши с зажатым шифтом, и удивился, что в виндовс такая полезная фича есть и для сторонних программ.
                +1
                Стоит отметить, что лучше редактировать поставляющийся с приложением манифест, а не полностью заменять на свой. Плюс это ломает цифровую подпись, её тогда тоже лучше вырезать, проверив перед этим.
                  0
                  Вы безусловно правы. Помнится я пытался тогда как-то вытащить родной манифест, но что-то не вышло и я забросил это дело…
                  0
                  Есть ещё четвёртый тип программ:

                  4. программа говорит Windows, что умеет масштабироваться (в результате операционная система послушно отключает DPI-виртуализацию, выглядящую как увеличение с размытием), но ленивые / наивные программисты на самом деле не добавляют в программу вообще никакого кода для осуществления правильного масштабирования средствами самой программы — просто добавить в манифест флаг dpiAware=true (сюрприз!) недостаточно.

                  В результате наблюдаем окна, элементы интерфейса и текст, мелкие вплоть до невозможности чтения и работы с программой. К этой категории относятся, например, антивирус ESET NOD32 и панель управления ESI Juli@.
                    +1
                    Это второй тип.
                      0
                      Второй тип — это когда некоторые элементы всё-таки масштабируются. А четвёртый — это когда масштабирования вообще не происходит, и единственное, что предпринял умница-автор программы — отключил DPI-виртуализацию.
                        0
                        Если просто взять, и отключить DPI-виртуализацию, то начинают масштабироваться системные или фреймворковые элементы управления (тайтл бары, кнопки, менюшки и т.д.), т.е. приложение переходит во вторую группу. От этого как раз страдает абсолютное большинство Qt приложений, как в топике.

                        А если не придираться к формулировкам, то эффект одинаковый — пользоваться приложением очень сложно, а переключить штатными средствами в адекватный режим нельзя.
                          0
                          Автомасштабирование кнопок при отключённой DPI-виртуализации — это, возможно, что-то специфичное для Qt (либо, может быть, на уровне системы увеличен не масштаб, а лишь размер шрифта). Окно обычной WinAPI-программы будет целиком равномерно очень мелким вместе со всеми содержащимися в нём элементами, включая кнопки. «Обвязочные» элементы интерфейса типа заголовочной панели окна — это, пожалуй, то немногое, что система способна адекватно масштабировать самостоятельно.
                            0
                            Вы попросту не правы. Классические WinAPI контролы прекрасно умеют масштабироваться самостоятельно. Проблема в юзер коде, который считает координаты в других величинах. Проверьте сами: возьмите какое-нибудь древнее приложение пятнадцатилетней давности и добавьте туда манифест с dpiAware=true. Вы будете удивлены!
                              0
                              возьмите какое-нибудь древнее приложение пятнадцатилетней давности и добавьте туда манифест с dpiAware=true.
                              Ок, можете привести конкретный пример такого приложения?
                                0
                                Возьмите что-нибудь из Windows XP например. Paint, Minesweeper или калькулятор.
                                  0
                                  Предполагаю, такие программы на самом деле вычисляют размеры всех элементов с учётом системного значения DPI, просто не сообщают об этом системе. Я же говорил об обратной ситуации: когда программа сообщает системе, что является DPI-aware, а на самом задаёт все размеры без учёта системного значения DPI.
                                    0
                                    Строго говоря, так практически не бывает. Я думаю, вы просто не найдёте такого приложения. Неплохой попыткой мог бы быть Chrome, но его основной процесс использует GetSystemMenu, а оно скалируется от DPI.

                                    Вы задаёте слишком строгие рамки, таких приложений не существует. А всё остальное попадает под категорию 2.

                                    В любом случае, я думаю мы друг друга поняли. Я с вами согласен насчёт таких программ, как Adobe Photoshop — ими пользоваться совершенно невозможно. :(
                                      0
                                      Я думаю, вы просто не найдёте такого приложения.
                                      Я же привёл примеры: ESET NOD32 и панель управления ESI Juli@ (см. скриншот). (Впрочем, в NOD32 окно дополнительных настроек всё-таки масштабируется, а мелкими [выводимыми пиксел в пиксел вне зависимости от DPI] являются основное окно, окно результатов сканирования и меню пиктограммы в области уведомлений.)

                                      Кстати, в Photoshop, согласно онлайн-документации Adobe, начиная с версии CC 2014 появилась экспериментальная настройка, включающая масштаб 200% для элементов интерфейса — правда, похоже, гибкая поддержка произвольного масштаба (например, 150% или 400%) пока не предусмотрена, т. е., скажем, на 8K-дисплеях проблема снова всплывёт.
                                        0
                                        У вас на скриншоте меню скалируется.
                                  0
                                  Могу сам сказать, как разработчик приложения на Winapi, что в моем приложении все прекрасно заработало после добавления манифеста, кроме самописных контролов, в которых я не учитывал DPI, а всё жестко указывал в пикселях. Больше НИКАКИХ изменений не потребовалось.
                              0
                              Посыпаю голову пеплом — моя вина с формулировками. Правильно было бы:
                              • сообщает виндовс, что умеет масштабироваться — и это правда
                              • сообщает виндовс, что умеет масштабироваться — но это ложь
                              • молчит или сообщает, что не умеет
                        0
                        А вы про какую Windows говорите? В Windows 8.1, появился: «Per monitor-DPI aware».
                        Про «DPI aware» в Windows
                        QTIPlot или QT это учитывают? Может в этом проблема? И на Windows < 8.1 все нормально.
                        Попробуйте отключить, «Per monitor-DPI aware», на Windows 8.1 это возможно.
                          0
                          Нет, Qt начал хоть как-то поддерживать PM только с версии 5.4, а в QTIplot вообще четвертая.
                            0
                            Да, все тесты проводились на Windows 8.1. Так как в теории я не силен, то еще в самом начале я перепробовал все настройки масштабирования в windows до которых смог добраться — ничего не помогло.
                            +1
                            А вот такой вопрос — имеются 2 монитора, один 3k(2880x1620) и обычный fullhd(1920x1080). Выставляешь масштабирование 150% — на первом всё замечательно, а на втором — ПРОСТО ПИПЕЦ, КАКОЕ ВСЁ БОЛЬШОЕ! Выставляешь 100% — на втором всё отлично, на первом — не разглядишь. Есть ли какая-то возможность задать разное масштабирование для разных мониторов в Win 8.1 Pro?
                              0
                              Один из мониторов ноутбук?
                                0
                                Да, вот такой: market.yandex.ru/product/10963143/?hid=91013&clid=698
                                0
                                Конечно, как одна из фич 8.1: Windows 8.1 DPI Scaling Enhancements. Конкретно вас интересует одна галочка «Let me choose one scaling level for all my displays» (извините, я не знаю, как локализовали на русский), её нужно снять, и вы сможете выбрать разное масштабирование для разных мониторов.
                                  0
                                  Пипец, и как это в своем коде поддерживать?
                                  Мало того, что нужно учитывать разный DPI, так еще у разных мониторов может быть разный DPI?
                                  То есть если окно программы перенесли на другой экран, она должна всё перемасштабировать?
                              0
                              Попробовал. Ничего не изменилось. ЧЯДНТ?
                                0
                                У меня три варианта:
                                1. этот метод не подходит для Вашей программы
                                2. этот метод не подходит для Вашей версии виндовс
                                3. вы и впрямь ЧДНТ.
                                Попробуйте на QTIPlot (в сети можно найти скомпилированную версию) — для нее-то должно сработать!
                                  0
                                  А на какой версии Windows оно должно работать? Пробовал на Win8.1.
                                    0
                                    На Win8.1 точно должно работать — я на этой версии всё делал. Вы пробовали это на qtiplot?
                                      0
                                      Нет, на другой программе. Собственно, я думал что это универсальная инструкция. :)

                                      Правда, я её же опробовал на своём собственном приложении под Qt 5.4 — оно тоже ничего не изменило.
                                0
                                Кстати, Skype от самого майкрософта до сих пор не DPI-aware. Интересно почему.
                                  0
                                  А не пробовали applicationName.exe -platform windows:dpiawareness=0 (https://doc-snapshots.qt.io/qt5-5.4/highdpi.html)?
                                  Еще можно попробовать выключить масштабирование на вкладке совместимости.
                                    0
                                    Эта опция появилась только в Qt5, а QTIPlot на четвертом.
                                    Масштабирование на вкладке совместимости — это для отключения масштабирования средствами Windows, т.е. имеет эффект только для программ третьего типа (так сказать, превращает программы третьего типа в программы второго типа :) )

                                  Only users with full accounts can post comments. Log in, please.