Windows 显示缩放设为 125% 或 150% 后,桌面程序可能同时遇到逻辑坐标、物理像素和窗口客户区三套尺度。金手指当前会在创建 Tk 窗口、执行截图和发送鼠标输入之前启用 DPI 感知,并优先使用 Per-Monitor V2;系统不支持时再依次尝试较早的 DPI API。这个处理用于让截图坐标和鼠标坐标尽量落到同一物理像素体系,但实际排错仍需同时核对窗口、模板和前台状态,不能只靠修改一个缩放百分比。
先区分桌面缩放与游戏窗口缩放
Windows 的 125% 或 150% 是系统显示缩放;游戏窗口本身还可能被拖大、缩小,或在 1080P 与 2K 屏幕上使用不同客户区尺寸。前者影响应用看到的坐标体系,后者改变画面中按钮相对于模板的像素大小。两种变化表面上都像“点偏了”,处理方法却不同:系统坐标不一致要先确认 DPI 感知与窗口矩形,模板大小不一致则要检查多尺度匹配和搜索区域。
排查时先记录桌面分辨率、Windows 缩放比例、目标窗口外框尺寸和客户区尺寸。不要在一次测试中同时改桌面缩放、拖动窗口、替换模板和降低阈值。每轮只变一个条件,才能知道偏移来自哪一层。

DPI 感知必须早于界面与截图初始化
当前 safe_clicker.py 在模块加载阶段执行 DPI 感知,并在安全点击器初始化时再次确认。首选的 Per-Monitor V2 适用于多显示器和 Windows 10/11 缩放环境;若调用失败,再尝试 SetProcessDpiAwareness(2) 与 SetProcessDPIAware()。顺序的意义在于尽早确定进程坐标语义,避免 Tk 窗口、Win32 窗口矩形和 PyAutoGUI 截图在初始化后各自保留不同解释。
用户侧不需要手工调用这些 API,但应避免同时打开多份不同版本程序控制同一批窗口。若旧版本在启动时没有相同 DPI 处理,而新版本已经启用,两个进程对同一窗口的截图和点击可能产生不同结果,日志也难以对应。
点击坐标应从当前窗口矩形重新计算
金手指的关键搜索区域使用相对于游戏窗口的比例,而不是把 1920×1080 桌面上的绝对坐标写死。队长窗口移动后,程序通过窗口句柄重新读取矩形,再把相对区域换算到屏幕坐标。标题栏、边框和客户区不能混作同一个原点;尤其在高 DPI 下,标题栏视觉高度占比会变化,代码中对部分区域还保留了轻微纵向修正,避免点击落到标题栏。
如果识别框在目标按钮上,而鼠标最终落到固定方向的偏移位置,优先检查截图与鼠标是否使用同一屏幕、窗口是否在识别后又被移动、前台窗口是否被其他应用抢走。若识别框本身就偏离目标,则先查区域比例和窗口矩形,不要直接补一个固定像素偏移,因为固定补偿在另一台分辨率或另一种缩放下会继续失效。
模板尺寸问题由多尺度匹配处理
当前安全点击器保留从小比例到较大比例的模板候选,用于覆盖不同游戏窗口尺寸、DPI 和模板采样差异。多尺度并不是把所有比例都无条件点击:候选必须仍在限定区域内达到对应阈值,部分入口还会结合文字、页签或同一行关系复核。搜索区域越准确,越能减少放大模板在无关画面中产生相似候选。
出现“能找到但分数很低”时,保存原始窗口截图和模板尺寸,比较目标在截图中的实际宽高比例。模板如果来自约 640 像素宽窗口,而当前客户区明显更大,就应先确认候选比例是否覆盖真实大小;出现“高分但点错对象”时,则要检查区域和语义复核,而不是继续扩大尺度范围。
用同一帧证据确认识别与点击
高 DPI 排错最有价值的证据是一张同帧截图:同时保留目标窗口矩形、搜索区域、最佳匹配框、分数和预期点击点。先隐藏账号、卡密、用户名、消息与其他隐私,再保存诊断图。只记录“鼠标点偏了”不能判断截图坐标是否正确,也无法确认点击前窗口是否已经被遮挡。
建议按顺序验证:窗口矩形是否围住正确客户端;搜索区域是否覆盖目标;最佳匹配框是否落在真实按钮;换算后的屏幕点是否仍在该框内;发送点击时前台句柄是否还是目标窗口。前四项正确而最后一项变化,问题在窗口激活;匹配框错误,问题在视觉条件;框正确但点不在框内,才应继续检查坐标转换。
现场排查的最小清单
保持目标梦幻西游手游时空客户端可见且不被遮挡,记录 Windows 缩放与屏幕分辨率;用相同窗口尺寸连续复现两次;查看日志中的窗口标题、尺寸、匹配分数与点击位置;再把窗口移动到同一显示器另一处复测。跨显示器时,如果两块屏幕缩放不同,应重新让目标窗口稳定停留后再运行,不要在截图和点击之间拖动。
这套方法解决的是证据链和坐标一致性,不代表任何界面变化都可自动吸收。窗口相对区域的基础原理可阅读游戏窗口移动后的图像识别,模板比例与阈值的关系见OpenCV 多尺度模板匹配实践。

