我有以下鼠标挂钩程序(为简化说明)。
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的坐标,而鼠标钩会给出未调整的数字。
如果程序不支持DPI,则系统会补偿缩放因子,以使程序保持运行状态,好像什么也没发生。
这正是返回值GetCursorPos
发生的情况。它提供的是逻辑像素,而不是物理像素。
另一方面,系统没有调整鼠标挂钩过程。
我尝试通过以下方式在清单中将程序设置为不识别DPI:
<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等中。
我不明白微软为什么决定向后退。没有表现出DPI意识的程序应表现正常,而不是相反。
这意味着每当在监视器上设置比例因子时,默认情况下大多数程序都会中断。为了破解它们,它们必须具备DPI意识,并且……就这样……它们将再次起作用。
答案 0 :(得分:-1)
我不明白为什么Microsoft决定倒退。不能表现DPI意识的程序应表现正常,而不是相反。
实际上,Microsoft的文档解释了此问题。
从High DPI Desktop Application Development on Windows,
使用较旧的Windows编程技术的桌面应用程序(原始 Win32编程,Windows窗体,Windows Presentation Framework (WPF等)无法自动处理DPI缩放 额外的开发人员工作。没有这样的工作,应用程序就会出现 在许多常见的使用场景中,图像模糊不清或大小不正确。
如果要避免DPI意识问题,请创建一个UWP
应用程序。
首先,如果要从头开始创建新的Windows应用程序, 强烈建议您创建一个Universal Windows Platform(UWP) 应用。 UWP应用程序可以自动,动态地扩展以适应 他们正在运行的每个显示器。