Активная доступность и масштабирование экрана Windows Vista
Windows Vista позволяет пользователям изменять параметр dots-per-inch (dpi), чтобы большинство элементов пользовательского интерфейса на экране отображались больше. Хотя эта функция уже давно доступна в Microsoft Windows, в предыдущих версиях масштабирование должно быть реализовано приложениями. В Windows Vista диспетчер окон рабочего стола выполняет масштабирование по умолчанию для всех приложений, которые не обрабатывают собственное масштабирование. Клиентские приложения Microsoft Active Accessibility должны учитывать эту функцию.
Масштабирование в Windows Vista
Параметр dpi по умолчанию равен 96, что означает, что 96 пикселей занимают ширину или высоту одного нотального дюйма. Точная мера «дюйма» зависит от размера и физического разрешения монитора. Например, на мониторе 12 дюймов в ширину при горизонтальном разрешении 1280 пикселей горизонтальная линия 96 пикселей расширяется примерно на 9/10 дюйма.
Изменение параметра dpi не совпадает с изменением разрешения экрана. При масштабировании dpi количество физических пикселей на экране остается неизменным. Однако масштабирование применяется к размеру и расположению элементов пользовательского интерфейса. Это масштабирование можно выполнять автоматически диспетчером окон рабочих столов (DWM) для рабочего стола и для приложений, которые явно не запрашивают масштабирование.
По сути, когда пользователь устанавливает коэффициент масштабирования на 120 dpi, вертикальный или горизонтальный дюйм на экране становится больше на 25 процентов. Все измерения масштабируются соответствующим образом. Смещение окна с верхних и левых краев экрана увеличивается на 25 процентов. Размер окна увеличивается в той же пропорции, а также смещения и размеры всех элементов пользовательского интерфейса, содержащихся в нем.
По умолчанию DWM не выполняет масштабирование для приложений, не поддерживающих dpi, когда пользователь устанавливает значение dpi 120, но выполняет его, когда для dpi установлено настраиваемое значение 144 или выше. Однако пользователь может переопределить поведение по умолчанию.
Масштабирование экрана создает новые проблемы для приложений, которые каким-либо образом работают с координатами экрана. Теперь экран содержит две системы координат: физические и логические. Физические координаты точки — это фактическое смещение в пикселях в левом верхнем углу источника. Логические координаты — это смещения, как они были бы, если бы сами пиксели были масштабированы.
Предположим, что вы разрабатываете диалоговое окно с кнопкой с координатами (100, 48). Если это диалоговое окно отображается по умолчанию 96 dpi, кнопка находится в физических координатах (100, 48). В 120 dpi он расположен в физических координатах (125, 60). Но логические координаты одинаковы при любом параметре dpi: (100, 48).
Логические координаты важны, так как они делают поведение операционной системы и приложений согласованными независимо от параметра dpi. Например, System.Windows.Forms.Cursor.Position обычно возвращает логические координаты. При перемещении курсора над элементом в диалоговом окне возвращаются те же координаты независимо от параметра dpi. Если вы рисуете элемент управления на координатах (100, 100), он рисуется по этим логическим координатам и будет занимать ту же относительную позицию при любом значении dpi.
Масштабирование в клиентах Active Accessibility
Microsoft Active Accessibility не использует логические координаты. Следующие методы и функции либо возвращают физические координаты, либо принимают их в качестве параметров.
По умолчанию клиентское приложение Microsoft Active Accessibility, работающее в среде, отличной от 96-dpi, не сможет получить правильные результаты из этих вызовов. Например, поскольку позиция курсора находится в логических координатах, клиент не может просто передать эти координаты в AccessibleObjectFromPoint, чтобы получить элемент, расположенный под курсором.
Кроме того, приложение, создающее окно вне клиентской области, например приложение специальных возможностей, которое выделяет элементы пользовательского интерфейса, не создаст окно в правильном расположении экрана, так как окно будет помещено в логические координаты, а не физические координаты, возвращаемые IAccessible::accLocation.
Решение состоит из двух частей:
- Сделайте клиентское приложение "dpi-aware". Для этого вызовите функцию SetProcessDPIAware при запуске. Эта функция делает весь процесс учитывающим dpi, что означает, что все окна, принадлежащие процессу, не масштабируются.
- Используйте функции с поддержкой dpi. Например, чтобы получить координаты курсора, вызовите функцию GetPhysicalCursorPos. Не используйте GetCursorPos; его поведение в приложениях с поддержкой dpi не определено.
Если ваше приложение выполняет прямой межпроцессный обмен данными с приложениями, которые не поддерживают DPI, возможно, вам придется выполнять преобразование между логическими и физическими координатами с помощью функций PhysicalToLogicalPoint и LogicalToPhysicalPoint.