不使用外部库实现Python鼠标指针移动报错排查
问题分析与修复
报错核心原因
代码在new_x相关计算处报错,主要有两个问题:
- 除零错误:
user32.GetSystemMetrics未指定返回值类型,ctypes默认将其视为c_int,部分环境下调用失败会返回0,导致后续new_x / screen_width触发ZeroDivisionError。 - API调用不规范:未正确定义
GetCursorPos所需的POINT结构体,可能引发内存访问问题或获取错误的光标坐标;且mouse_event属于Windows废弃API,调用逻辑存在潜在兼容性问题。
修复后的代码
import ctypes import time # 定义Windows原生POINT结构体,匹配API参数要求 class POINT(ctypes.Structure): _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)] MOUSEEVENTF_MOVE = 0x0001 MOUSEEVENTF_ABSOLUTE = 0x8000 target_x = 500 target_y = 500 movement_amount = 50 # 加载user32并指定函数参数/返回值类型,避免类型错误 user32 = ctypes.WinDLL('user32', use_last_error=True) user32.GetSystemMetrics.argtypes = [ctypes.c_int] user32.GetSystemMetrics.restype = ctypes.c_int user32.GetCursorPos.argtypes = [ctypes.POINTER(POINT)] user32.GetCursorPos.restype = ctypes.c_bool user32.mouse_event.argtypes = [ctypes.c_uint, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint, ctypes.c_ulonglong] screen_width = user32.GetSystemMetrics(0) screen_height = user32.GetSystemMetrics(1) # 提前校验屏幕分辨率有效性,避免除零 if screen_width == 0 or screen_height == 0: raise RuntimeError("无法获取有效屏幕分辨率") while True: original_pos = POINT() if not user32.GetCursorPos(ctypes.byref(original_pos)): raise RuntimeError("无法获取当前光标位置") new_x = target_x + movement_amount new_y = target_y + movement_amount # 计算绝对坐标,限制在0-65535范围内(符合MOUSEEVENTF_ABSOLUTE要求) absolute_x = min(max(int(new_x / screen_width * 65535), 0), 65535) absolute_y = min(max(int(new_y / screen_height * 65535), 0), 65535) user32.mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, absolute_x, absolute_y, 0, 0) time.sleep(1) # 计算原位置的绝对坐标并返回 orig_abs_x = int(original_pos.x / screen_width * 65535) orig_abs_y = int(original_pos.y / screen_height * 65535) user32.mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, orig_abs_x, orig_abs_y, 0, 0) time.sleep(10)
关键修复点
- 定义
POINT结构体:严格匹配Windows API的参数结构,避免内存访问异常。 - 指定函数类型:给所有调用的user32 API明确
argtypes和restype,确保ctypes正确处理数据类型转换。 - 添加前置校验:提前检查屏幕分辨率是否有效,从根源避免除零错误。
- 限制坐标范围:确保计算出的绝对坐标在
MOUSEEVENTF_ABSOLUTE要求的0-65535区间内,避免无效坐标输入。
内容的提问来源于stack exchange,提问作者AdmiralJack
相关产品推荐
相关产品推荐

