Python自动点击器功能异常及热键触发问题求助
Python自动点击器功能异常及热键触发问题求助
我正在尝试制作一个自动点击器,它需要先检查点击器是否启用,然后检查用户是否按住鼠标左键。如果满足条件,程序会在一定延迟范围内点击。当用户释放左键时,自动点击应该停止。我目前的代码可以正常启用和禁用,但当我按住鼠标按钮时,只能得到1-2次点击,然后就停止了。
第二个问题是,使用自动点击器的热键时,我必须不按任何其他键才能激活热键。例如,在玩游戏时,我无法一边移动(按其他键)一边启用或禁用自动点击器。
如果有人能解决这两个问题,我将非常感谢任何建议。
我来帮你分析这两个问题并给出修复方案:
问题1:按住左键仅触发1-2次点击就停止
核心原因:
- 旧版
mouse_eventAPI模拟的点击会干扰GetAsyncKeyState的检测——当程序模拟左键松开时,会让检测函数误以为用户已经松开了左键,直接退出循环。 - 嵌套循环逻辑有缺陷:一旦单次检测到左键状态为
False(哪怕是模拟点击导致的),就会完全退出内部触发逻辑,必须等用户松开再按下左键才会重新启动。
修复方案:
- 改用Windows推荐的
SendInputAPI模拟输入,它不会干扰物理按键的状态检测; - 重构循环逻辑,将嵌套循环改为单循环,每次迭代都重新检查启用状态和用户的左键按压状态,避免单次检测错误导致停止。
问题2:热键需松开其他键才能触发
核心原因:keyboard.add_hotkey默认采用"严格匹配"逻辑——只有当目标键单独按下时才会触发,其他按键按住时会被忽略,这在游戏场景下非常受限。
修复方案:
改用keyboard.on_press_key监听按键事件,它会直接响应目标键的按下动作,无论你是否按住其他按键。
修改后的完整代码
import ctypes import time import threading import random import keyboard # Constants for Windows API mouse events MOUSEEVENTF_LEFTDOWN = 0x0002 MOUSEEVENTF_LEFTUP = 0x0004 VK_LBUTTON = 0x01 # Virtual key code for the left mouse button # Windows API functions user32 = ctypes.windll.user32 # 定义SendInput所需的结构体(替代旧版mouse_event) class MOUSEINPUT(ctypes.Structure): _fields_ = [ ("dx", ctypes.c_long), ("dy", ctypes.c_long), ("mouseData", ctypes.c_uint), ("dwFlags", ctypes.c_uint), ("time", ctypes.c_uint), ("dwExtraInfo", ctypes.c_void_p) ] class INPUT(ctypes.Structure): _fields_ = [ ("type", ctypes.c_uint), ("mi", MOUSEINPUT) ] INPUT_MOUSE = 0 def send_mouse_input(flags): """使用SendInput模拟鼠标输入,更可靠且不干扰物理按键检测""" mi = MOUSEINPUT(0, 0, 0, flags, 0, None) inp = INPUT(INPUT_MOUSE, mi) user32.SendInput(1, ctypes.byref(inp), ctypes.sizeof(inp)) def click(): """模拟一次完整的左键点击""" send_mouse_input(MOUSEEVENTF_LEFTDOWN) send_mouse_input(MOUSEEVENTF_LEFTUP) def is_left_mouse_button_pressed(): """检测用户物理左键是否按住""" return user32.GetAsyncKeyState(VK_LBUTTON) & 0x8000 != 0 # Control variables enabled = False # Toggle for enabling/disabling the clicker # Hotkeys ENABLE_KEY = 'g' # Press 'g' to enable/disable auto-clicking EXIT_KEY = '0' # Press '0' to exit def clicker(): """重构后的点击循环逻辑,避免单次检测错误导致停止""" while True: if enabled and is_left_mouse_button_pressed(): click() # 随机延迟,同时降低被反作弊系统识别的风险 time.sleep(random.uniform(0.05, 0.3)) # 缩短非点击状态的延迟,提高响应速度 time.sleep(0.001) def toggle_clicking(): global enabled enabled = not enabled print(f"Auto-clicker {'enabled' if enabled else 'disabled'}") # Start clicking thread clicking_thread = threading.Thread(target=clicker, daemon=True) clicking_thread.start() # 设置热键:改用on_press_key,支持按住其他键时触发 keyboard.on_press_key(ENABLE_KEY, lambda event: toggle_clicking(), suppress=False) # Wait for exit key keyboard.wait(EXIT_KEY)
额外说明
- SendInput的优势:作为Windows官方推荐的输入模拟API,它的行为更接近物理输入,不会干扰对用户实际按键的检测,同时也更不容易被游戏反作弊系统识别。
- 循环逻辑优化:单循环每次都会重新检查状态,哪怕某次检测因为临时干扰返回
False,下一次迭代依然会响应用户的按住操作。 - 热键触发优化:
on_press_key直接监听目标键的按下事件,游戏中按住WASD等移动键时,依然可以正常触发自动点击器的启停。
备注:内容来源于stack exchange,提问作者Matteo
相关产品推荐
相关产品推荐

