Настройка осведомленности о DPI процесса, чтобы система компенсировала коэффициенты масштабирования - PullRequest
1 голос
/ 21 июня 2020

У меня есть следующая процедура перехвата мыши (упрощенная для объяснения).

SetWindowsHookEx(WH_MOUSE_LL, mouseHookProc, GetModuleHandle(NULL), 0) ;

LRESULT mouseHookProc(int code, WPARAM wParam, LPARAM lParam){
    if(code==HC_ACTION){
        const auto& data = *(MSLLHOOKSTRUCT*)lParam ;
        
        data.pt ; //This point gives physical coordinates. It ignores the monitor's scaling factor.
        //https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msllhookstruct
    }
    return CallNextHookEx(NULL, code, wParam, lParam) ;
}

Координаты мыши, которые я получаю от перехватчика, не регулируются коэффициентом масштабирования монитора. Независимо от того, устанавливаю ли я коэффициент масштабирования монитора на 100% или 200%, крючок мыши всегда дает мне физические пиксели.

С другой стороны, функция GetCursorPos winapi выдает координаты в логических пикселях. т.е. если коэффициент масштабирования равен 200%, GetCursorPos даст координаты, разделенные на 2, тогда как крючок мыши даст числа без корректировки.

Согласно этому: https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-process_dpi_awareness

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

Именно это происходит с возвращенным значением GetCursorPos. Это дает логические пиксели, а не физические.

С другой стороны, процедура подключения мыши не регулируется системой.

Я попытался настроить свою программу как не поддерживающую DPI в manifest, с этим:

<asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
        <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">unaware</dpiAwareness>
    </asmv3:windowsSettings>
</asmv3:application>

Но это не имеет значения. Я также попытался объявить его как поддерживающий DPI, вот так:

<asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
        <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
        <dpiAware>True/PM</dpiAware>
    </asmv3:windowsSettings>
</asmv3:application>

И это тоже не имело никакого значения.

Есть ли какие-то настройки, которые я могу добавить в свою программу, либо через манифест или иначе, что заставит процедуру перехвата мыши давать логические координаты, как GetCursorPos?

Я тестирую все это в Windows 10.

ПОСЛЕДУЮЩИЕ:

Я обнаружил проблему. Мой файл манифеста был неверным. Пространства имен XML не были установлены должным образом.

Вот тот, который работает.

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> 
    <assemblyIdentity version="1.0.0.0" name="AppName" type="win32"/>
    <asmv3:application>
        <asmv3:windowsSettings>
            <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
            <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>
</assembly>

Чтобы система давала программе логические координаты, программа должна быть С учетом DPI. Программы, в которых отсутствует поддержка DPI, будут обрабатывать координаты непоследовательно повсюду, не только на крючке мыши, но и в BitBlt, IAccesibility, UIAutomation и т. Д. c.

Я не понимаю, почему Microsoft решила сделать это наоборот. Программы, в которых отсутствует поддержка DPI, должны вести себя как обычно, а не наоборот.

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

1 Ответ

0 голосов
/ 22 июня 2020

Я не понимаю, почему Microsoft решила сделать это задом наперед. Программы, в которых отсутствует поддержка DPI, должны вести себя как обычно, а не наоборот.

Фактически, Microsoft do c объясняет эту проблему.

From Разработка настольных приложений с высоким разрешением на Windows,

Настольные приложения с использованием более старых Windows технологий программирования (программирование под Win32, Windows Forms, Windows Presentation Framework (WPF) , et c.) не могут автоматически обрабатывать масштабирование DPI без дополнительных усилий разработчика. Без такой работы приложения будут выглядеть размытыми или иметь неправильный размер во многих распространенных сценариях использования ios.

Если вы хотите избежать проблем с распознаванием DPI, создайте приложение UWP.

Для начала, если вы создаете новое приложение Windows с нуля, настоятельно рекомендуется создать приложение Universal Windows Platform (UWP). Приложения UWP автоматически и динамически масштабируются для каждого дисплея, на котором они работают.

...