当前位置: 首页 > news >正文

python模拟键盘 鼠标操作 通过ctypes调用Windows API实现底层输入模拟

Windows下Python自动键鼠模拟器源码详解

本文介绍一个基于Python的Windows键盘鼠标自动化模拟器,适合自动化测试、游戏辅助等场景。代码通过ctypes调用Windows API实现底层输入模拟。

实测案例:bongo cat刷点击
在这里插入图片描述

1. 主要功能

  • 模拟键盘按键(按下、释放、完整按键)
  • 模拟鼠标点击(左键、右键,可指定坐标)
  • 支持绝对坐标定位
  • 可自定义点击间隔和范围

2. 代码结构

2.1 InputSimulator类

负责封装所有输入模拟相关方法。

class InputSimulator:def __init__(self):self.user32 = ctypes.WinDLL('user32', use_last_error=True)# ... 定义各种常量 ...
主要方法
  • press_key(key_code):模拟按键按下
  • release_key(key_code):模拟按键释放
  • key_press(key_code, duration=0.1):完整按键(按下+延时+释放)
  • click_mouse(x=None, y=None):模拟鼠标左键点击(可指定坐标)
  • right_click_mouse(x=None, y=None):模拟鼠标右键点击(可指定坐标)

2.2 结构体定义

使用ctypes定义Windows API所需的结构体:

class MOUSEINPUT(ctypes.Structure):_fields_ = (("dx", wintypes.LONG),("dy", wintypes.LONG),("mouseData", wintypes.DWORD),("dwFlags", wintypes.DWORD),("time", wintypes.DWORD),("dwExtraInfo", ctypes.POINTER(wintypes.ULONG)))
# 还有 KEYBDINPUT 和 INPUT 结构体

2.3 示例用法

主程序部分演示了如何自动点击:

if __name__ == "__main__":import keyboardimport randomsimulator = InputSimulator()print("程序已启动,按Q键退出...")while True:if keyboard.is_pressed('q'):print("检测到Q键,程序退出")breakx = random.randint(1000, 1100)y = random.randint(700, 800)simulator.click_mouse(x, y)time.sleep(random.uniform(0.05, 0.1))
  • 随机生成点击坐标
  • 按Q键可随时退出

3. 技术要点

  • ctypes调用user32.dll:实现底层输入模拟
  • 支持绝对坐标:通过65535缩放映射屏幕坐标
  • 结构体封装:与Windows API参数完全兼容
  • 可扩展性强:可根据需要添加更多输入事件

4. 注意事项

  • 仅支持Windows系统
  • 需管理员权限
  • 请勿在重要操作界面误用

5. 应用场景

  • 自动化测试
  • 游戏脚本
  • 重复性办公自动化
  • 系统集成测试

完整代码见下方:

点击展开查看完整代码
import ctypes
import time
from ctypes import wintypesclass InputSimulator:def __init__(self):self.user32 = ctypes.WinDLL('user32', use_last_error=True)# Windows API 常量self.INPUT_MOUSE = 0self.INPUT_KEYBOARD = 1self.KEYEVENTF_KEYUP = 0x0002self.KEYEVENTF_UNICODE = 0x0004self.MOUSEEVENTF_LEFTDOWN = 0x0002self.MOUSEEVENTF_LEFTUP = 0x0004self.MOUSEEVENTF_RIGHTDOWN = 0x0008self.MOUSEEVENTF_RIGHTUP = 0x0010self.MOUSEEVENTF_MOVE = 0x0001self.MOUSEEVENTF_ABSOLUTE = 0x8000def press_key(self, key_code):"""模拟按键按下"""x = INPUT(type=self.INPUT_KEYBOARD,ki=KEYBDINPUT(wVk=key_code))self.user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))def release_key(self, key_code):"""模拟按键释放"""x = INPUT(type=self.INPUT_KEYBOARD,ki=KEYBDINPUT(wVk=key_code,dwFlags=self.KEYEVENTF_KEYUP))self.user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))def key_press(self, key_code, duration=0.1):"""模拟完整的按键过程"""self.press_key(key_code)time.sleep(duration)self.release_key(key_code)def click_mouse(self, x=None, y=None):"""模拟鼠标点击参数:x: 鼠标x坐标(可选)y: 鼠标y坐标(可选)"""if x is not None and y is not None:screen_width = self.user32.GetSystemMetrics(0)screen_height = self.user32.GetSystemMetrics(1)x = int(x * 65535 / screen_width)y = int(y * 65535 / screen_height)move = INPUT(type=self.INPUT_MOUSE,mi=MOUSEINPUT(dx=x, dy=y, dwFlags=self.MOUSEEVENTF_MOVE | self.MOUSEEVENTF_ABSOLUTE))self.user32.SendInput(1, ctypes.byref(move), ctypes.sizeof(move))time.sleep(0.1)down = INPUT(type=self.INPUT_MOUSE,mi=MOUSEINPUT(dwFlags=self.MOUSEEVENTF_LEFTDOWN))self.user32.SendInput(1, ctypes.byref(down), ctypes.sizeof(down))time.sleep(0.1)up = INPUT(type=self.INPUT_MOUSE,mi=MOUSEINPUT(dwFlags=self.MOUSEEVENTF_LEFTUP))self.user32.SendInput(1, ctypes.byref(up), ctypes.sizeof(up))def right_click_mouse(self, x=None, y=None):"""模拟鼠标右键点击"""if x is not None and y is not None:screen_width = self.user32.GetSystemMetrics(0)screen_height = self.user32.GetSystemMetrics(1)x = int(x * 65535 / screen_width)y = int(y * 65535 / screen_height)move = INPUT(type=self.INPUT_MOUSE,mi=MOUSEINPUT(dx=x, dy=y, dwFlags=self.MOUSEEVENTF_MOVE | self.MOUSEEVENTF_ABSOLUTE))self.user32.SendInput(1, ctypes.byref(move), ctypes.sizeof(move))time.sleep(0.1)down = INPUT(type=self.INPUT_MOUSE,mi=MOUSEINPUT(dwFlags=self.MOUSEEVENTF_RIGHTDOWN))self.user32.SendInput(1, ctypes.byref(down), ctypes.sizeof(down))time.sleep(0.1)up = INPUT(type=self.INPUT_MOUSE,mi=MOUSEINPUT(dwFlags=self.MOUSEEVENTF_RIGHTUP))self.user32.SendInput(1, ctypes.byref(up), ctypes.sizeof(up))# 保持原有的结构体定义
class MOUSEINPUT(ctypes.Structure):_fields_ = (("dx", wintypes.LONG),("dy", wintypes.LONG),("mouseData", wintypes.DWORD),("dwFlags", wintypes.DWORD),("time", wintypes.DWORD),("dwExtraInfo", ctypes.POINTER(wintypes.ULONG)))class KEYBDINPUT(ctypes.Structure):_fields_ = (("wVk", wintypes.WORD),("wScan", wintypes.WORD),("dwFlags", wintypes.DWORD),("time", wintypes.DWORD),("dwExtraInfo", ctypes.POINTER(wintypes.ULONG)))class INPUT(ctypes.Structure):class _INPUT(ctypes.Union):_fields_ = (("mi", MOUSEINPUT),("ki", KEYBDINPUT))_anonymous_ = ("_input",)_fields_ = (("type", wintypes.DWORD),("_input", _INPUT))# 使用示例
if __name__ == "__main__":"""# 创建模拟器实例simulator = InputSimulator()# 示例:模拟按下A键simulator.key_press(0x41)# 示例:模拟鼠标点击simulator.click_mouse()# 示例:在指定位置右键点击simulator.right_click_mouse(100, 100)"""import keyboardimport randomsimulator = InputSimulator()print("程序已启动,按Q键退出...")while True:if keyboard.is_pressed('q'):print("检测到Q键,程序退出")break# 随机坐标(在1000-1100和700-800范围内)x = random.randint(1000, 1100)y = random.randint(700, 800)# # 模拟鼠标右键点击# simulator.right_click_mouse(x, y)# time.sleep(random.uniform(0.05, 0.1))# 模拟鼠标左键点击simulator.click_mouse(x, y)time.sleep(random.uniform(0.05, 0.1))

相关文章:

  • Android Studio 问题:Android Studio 一直开在 Updating indexes
  • 使用Mvnd加速Maven构建速度
  • 深度学习核心概念:优化器、模型可解释性与欠拟合
  • TI以太网PHY收发器晶体选择和规格
  • OpenGL学习20250610
  • 定时器任务——若依源码分析
  • 376. Wiggle Subsequence
  • Windows cmd中文乱码解决方法(Windows控制台中文乱码、CMD乱码、控制台乱码、Command Prompt命令提示符cmd.exe乱码)
  • docker 安装运行mysql8.4.4
  • 多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
  • Loss Margin的原理与推导
  • 一天时间解决期末不挂科
  • 代码解读——ReferenceNet
  • 【位运算】消失的两个数字(hard)
  • STM32 PID控制
  • Hyperlane 框架详解与使用指南
  • shell打印图案
  • 常用的OceanBase调优配置参数
  • Maven 多仓库配置及缓存清理实战分享
  • 【Redis/1-前置知识】分布式系统概论:架构、数据库与微服务
  • 扁平化网站模板下载/培训机构加盟
  • 网站建设 淘宝详情/推广平台都有哪些
  • 网站上微信的链接怎么做/自己怎么开网站
  • 双语网站建设方案/上海外贸seo公司
  • 哈尔滨悦创网络科技网站开发/最有效的推广方式
  • 做电商海报的网站/惠州seo全网营销