Какую ошибку я, вероятно, исправил с помощью Disable Display Scaling?

Я унаследовал устаревшее приложение, которое теперь должно работать в Windows 10. Во время тестирования мы обнаружили, что часть программы (которая представляет собой дочернее окно, размещенное в виде панели инструментов) лишь частично отрисовывается при запуске программы — более половины справа от панели инструментов будет рисовать только черный цвет. Во время выполнения исправление заключалось в изменении размера всего окна, что приводило к изменению размера/перерисовке окна панели инструментов. В конце концов мы обнаружили, что если мы установим «Отключить масштабирование дисплея», это полностью предотвратит ошибку (до сих пор проверено с достоверностью чуть больше 1 из 10 000, что для меня достаточно хорошо).

Вопрос в том:

эта ошибка возникла только с вероятностью от 1/12 до 1/20 (что я определил из видео наших автоматических тестов программы, которые включали 185 возможностей для возникновения ошибки. Никакой закономерности возникновения обнаружено не было). Мне никогда не приходилось сталкиваться с такой ошибкой, и поэтому мне интересно: учитывая очевидную случайность ошибки и исправление, что происходит? Состояние гонки между рендерингом растрового изображения, которое Windows затем масштабирует для «высокого DPI», и функциями, которые размещают панель инструментов?


person Erin Anne    schedule 18.05.2017    source источник


Ответы (1)


Windows 10 расширила концепцию поддержки DPI. Раньше осведомленность о DPI была настройкой для каждого процесса, но теперь это концепция для каждого потока. документы MSDN формулировку теперь немного сложно расшифровать, но похоже, что вызов SetProcessDPIAwareness (что, как я ожидаю, делает устаревшее приложение) влияет только на вызывающий поток (несмотря на то, что «Процесс» находится в названии).

Теория № 1. Возможно, окно вашей панели инструментов иногда создается в потоке с поддержкой DPI, а иногда — в другом потоке.

Теория № 2: существует гонка между приложением, вызывающим SetProcessDPIAware, и некоторым кодом пользовательского интерфейса, кэширующим показатель отображения, который позже используется для рисования окна панели инструментов. В зависимости от того, кто выиграет гонку, вы можете получить неправильное поведение.

Документы предполагают, что более старые приложения (также известные как устаревшие приложения) устанавливали осведомленность о DPI для всего процесса, используя настройку манифеста. Я полагаю, что это гарантирует, что параметр будет применен ко всем потокам в процессе, и это должно произойти до запуска любого пользовательского кода, поэтому не должно быть гонки. Поскольку отключение масштабирования, по-видимому, решает проблему, а настройка осведомленности о DPI должна быть примерно эквивалентна этому (фактически), я ожидаю, что это решит проблему, если любая из теорий верна.

документация для SetProcessDpiAware объясняет, как настроить поддержку DPI с помощью манифеста.

person Adrian McCarthy    schedule 18.05.2017
comment
Я думаю, что понял это в вашем первом абзаце, но просто чтобы быть уверенным - я использую флаги совместимости либо в ярлыке, либо в свойствах самого EXE (как установлено в реестре ), чтобы отключить осведомленность о DPI, так что вы думаете, что SetProcessDPIAwareness вызывается, потому что это установлено? Манифесты, вероятно, появятся в будущих версиях, но, к сожалению, следующая версия, вероятно, выйдет через некоторое время. - person Erin Anne; 19.05.2017
comment
Не совсем. Отключение масштабирования в свойствах не приводит к вызову SetProcessDPIAwareness, но имеет аналогичный эффект. Поскольку кажется, что это всегда работает, когда вы вручную отключаете масштабирование, я подозреваю, что код написан для понимания высокого DPI. Поскольку иногда это работает, когда вы не отключаете масштабирование, я думаю, что программа пытается сообщить ОС, что она поддерживает DPI (путем вызова SetProcessDPIAware или SetProcessDPIAwareness), но либо она не применяется ко всем потокам (Windows 10 изменила это), либо есть состояние гонки (поэтому иногда оно сообщает ОС слишком поздно). - person Adrian McCarthy; 19.05.2017
comment
Код приложения точно не понимает High DPI (или совсем не понимает), но все элементы графического интерфейса стандартные для Win32, так что я не знаю, что там происходит. Мы также не запускали его ни на одной из ОС между Win 7 и Win 10, поэтому я не смог бы определить, в каких версиях ОС обнаружена ошибка (за исключением того, что в 7 нет, а в 10 есть). Еще одна причина, по которой мы считали высокий DPI проблемой, заключалась в том, что автоматическое тестирование начинало щелкать в неправильном месте при попытке взаимодействовать со строкой меню... состояние гонки теперь кажется более правдоподобным. - person Erin Anne; 19.05.2017