Подтвердить что ты не робот

Получение DPI с учетом правильного RECT из GetWindowRect из внешнего окна

Я делаю приложение DPI Aware, но мне нужно сделать GetWindowRect для HWND из других приложений. Моя проблема заключается в том, что это отлично подходит для приложений, которые также являются программным обеспечением DPI Aware, но как определить, является ли дескриптор HWND виртуализированным DPI, например. масштабируется, поэтому я могу масштабировать его сам? Или есть другие API-интерфейсы, которые я пропустил, что даст мне размер окна в режиме DPI из HWND из другого процесса?

Я пробовал LogicalToPhysicalPoint, но всегда сбой, возможно, потому, что HWND не принадлежит моему приложению.

4b9b3361

Ответ 1

Это не настоящая проблема. Если вы отметите свой процесс как осведомленный о высоком DPI, тогда система больше не будет делать каких-либо виртуализации DPI, и API больше не будут лгать вам о фактических значениях.

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

Начиная с Windows 8.1, PhysicalToLogicalPoint и LogicalToPhysicalPoint функции больше не нужны и фактически ничего не делают. Документация для этих двух функций вызывает это явно:

В Windows 8.1 дополнительная виртуализация системы и межпроцессорная коммуникация означают, что для большинства приложений вам не нужны эти API. В результате в Windows 8.1, PhysicalToLogicalPoint и LogicalToPhysicalPoint больше не преобразуются точки. Система возвращает все точки в приложение в своем собственном пространстве координат.

Последнее предложение - это просто другой способ выражения того, что я сказал выше. Система возвращает значения в соответствии с осознанием DPI вызывающего абонента. Если ваш процесс имеет высокий уровень DPI, то вы получите реальные значения. Вам не нужно масштабировать значения самостоятельно. Если вы не осведомлены о высоком уровне DPI, вы подвергаетесь лживым действиям относительно фактических значений. Но это имеет смысл, потому что предполагается, что вы не можете справиться с правдой и не будете реагировать соответствующим образом.

Чтобы быть ясным, я должен отметить, что в настоящее время на уровне Windows 8.1 (и продолжаются в Windows 10) на самом деле есть два уровня осведомленности о высоком уровне DPI:

  • Существует первый уровень, введенный обратно с Windows Vista, с высоким уровнем осведомленности о DPI. Это указывается параметром true в файле манифеста приложения, а это просто означает, что вы (приложение) можете иметь дело с системным DPI, который установлен на что-то отличное от классического значения по умолчанию 96 DPI.

    Исходя из вышеприведенных знаний, мы знаем, что если процесс с этим параметром информирования DPI вызывает функцию API, которая возвращает координаты экрана, она получит значения в терминах DPI системы.

  • Затем появился новый уровень, представленный в Windows 8.1, для обеспечения высокого уровня DPI для каждого монитора. Об этом указывает параметр True/PM в манифесте приложения, а это означает, что вы (приложение) можете иметь дело с различными мониторами, имеющими разные настройки DPI. Другими словами, хотя по-прежнему существует DPI по умолчанию (и может быть 96 DPI или это может быть что-то еще), могут быть подключены мониторы к системе, которые используют другую настройку DPI (что-то иное, чем системный DPI).

    Опять же, на основе вышеизложенного понимания, мы знаем, что если процесс, который для каждого монитора с высоким уровнем DPI, вызывает функцию API, которая возвращает экранные координаты, он получит фактические координаты относительно DPI монитора, который содержит соответствующее окно.

Если ваш процесс вообще не распознается DPI (нет значения в манифесте или false), то при вызове функций API, возвращающих координаты экрана, вы получите координаты, масштабированные/виртуализированные на основе общесистемного DPI 96 DPI.

Ответ 2

Флаг осведомленности DPI устанавливается на уровне приложения, а не на уровне окна. Поэтому, если вы можете получить процесс этого конкретного дескриптора окна другого приложения, вы можете использовать функцию GetProcessDpiAwareness(), чтобы получить флаг осведомленности о том, что процесс см. в документации по микрософт https://msdn.microsoft.com/en-us/library/windows/desktop/dn302113(v=vs.85).aspx