You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

跨不同屏幕分辨率的鼠标移动坐标转换问题求助

跨不同屏幕分辨率的鼠标移动坐标转换问题求助

大家好,我现在在做一个项目,需要把鼠标光标精准移动到屏幕上的特定坐标。为了让这个功能在不同屏幕分辨率下都能正常工作,我自己实现了一个坐标转换函数,再把转换后的坐标传给负责移动鼠标的mouse_move函数。

下面是我目前在用的代码:

from pyautogui import *
from win32api import SetCursorPos


def convert_cords(x, y):
    w, h = size()
    original_res = (1360, 768)
    ratio_x = w / original_res[0]
    ratio_y = h / original_res[1]
    new_x = round(x * ratio_x)
    new_y = round(y * ratio_y)
    return (new_x, new_y)

def mouse_move(x, y):
    new_x, new_y = convert_cords(x, y)
    SetCursorPos((new_x, new_y))

我的思路是这样的:convert_cords函数会拿目标的原始坐标(基于1360x768分辨率设定的),根据当前屏幕分辨率和基准分辨率的比例进行缩放,算出适配当前屏幕的新坐标;mouse_move则调用Windows的API来移动鼠标到转换后的位置。

不过实际测试的时候,我遇到了一些问题(比如鼠标移动的位置总是和预期有偏差,在开启DPI缩放的屏幕上完全找不到正确位置),有没有大佬能帮我排查一下问题,或者给我一些改进的建议?


可能的问题点与改进方案

我结合自己的经验整理了几个可能的原因,以及对应的解决思路:

  • DPI缩放的干扰:Windows的DPI缩放(比如125%、150%)会导致pyautogui.size()获取到的是逻辑分辨率,而SetCursorPos使用的是屏幕的物理分辨率,这就会导致坐标比例计算错误。你可以改用Windows API获取真实的物理分辨率:

    import win32gui
    import win32con
    from win32print import GetDeviceCaps
    
    def get_real_screen_res():
        hdc = win32gui.GetDC(0)
        real_width = GetDeviceCaps(hdc, win32con.DESKTOPHORZRES)
        real_height = GetDeviceCaps(hdc, win32con.DESKTOPVERTRES)
        win32gui.ReleaseDC(0, hdc)
        return (real_width, real_height)
    

    然后在convert_cords里替换size()为这个函数的返回值,就能得到准确的比例了。

  • 舍入方式的细微误差:使用round()做坐标取整,在某些缩放比例下可能会累积微小误差。如果追求极致精准,可以考虑用math.floor()或者math.ceil(),不过一般情况下round()已经足够,主要问题还是出在DPI上。

  • 多屏幕场景的适配:如果用户使用多显示器,pyautogui.size()返回的是主屏幕的分辨率,但SetCursorPos的坐标是相对于整个虚拟桌面的。这时候你需要先判断目标坐标属于哪个屏幕,再针对该屏幕的分辨率做转换,避免跨屏幕时的位置偏差。

另外,其实pyautogui自带的moveTo()函数已经内置了分辨率和DPI适配逻辑,如果你没有特殊需求,直接调用pyautogui.moveTo(x, y)可能更省心,不用自己手动处理转换。

备注:内容来源于stack exchange,提问作者Valgrind

火山引擎 最新活动