修复方案:SetProcessDPIAware 与 DPI 感知
修复只需一个 API 调用——告诉 Windows 你的应用理解高 DPI,要使用物理像素:
// C / C++ (Windows API)
SetProcessDPIAware();
// C# (.NET)
[DllImport("user32.dll")]
static extern bool SetProcessDPIAware();
SetProcessDPIAware();
// Python (ctypes)
import ctypes
ctypes.windll.user32.SetProcessDPIAware()
// Python(推荐,较新的 Windows)
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(2) // PROCESS_PER_MONITOR_DPI_AWARE
// Python(推荐,Windows 10 1703+ 和 Windows 11)
import ctypes
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = ctypes.c_void_p(-4)
ctypes.windll.user32.SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)
调用之后,坐标函数返回的就是物理像素值而非逻辑值。pyautogui.size() 会返回 3840×2160 而不是 2560×1440。pyautogui.position() 会返回真实的像素位置。你的点击会精确落在你期望的地方。
该用哪个调用?
API行为适用场景
SetProcessDPIAware()系统级 DPI 感知。获取主显示器的物理分辨率。单显示器,统一缩放。
SetProcessDpiAwareness(2)逐显示器 DPI 感知。获取每台显示器的真实物理分辨率。多显示器混合 DPI(Windows 8.1+)。
SetProcessDpiAwarenessContext(-4)逐显示器 DPI 感知 V2。同上,额外修复了混合 DPI 下标题栏和非客户区的缩放 bug。推荐用于 Windows 10 1703+ 和 Windows 11。参见我们的多显示器坐标指南。
应用清单方式(无需写代码)
如果你在开发 Windows 应用,可以在清单文件中声明 DPI 感知,不需要调用 API:
关于 PyAutoGUI 的完整修复方案(包括多显示器支持和截图区域偏移),参见我们的PyAutoGUI 坐标指南。