Python自动化(3)——鼠标模拟

news/2024/9/24 23:26:44/

Python自动化(3)——鼠标模拟

前台鼠标模拟

鼠标模拟和键盘模拟类似,也是分前台和后台模拟。话不多说直接,上代码:

python">import time
import win32api
import win32con
import win32gui
from ctypes import *MOUSEEVENTF_LEFTDOWN = 0x2
MOUSEEVENTF_LEFTUP = 0x4
MOUSEEVENTF_MIDDLEDOWN = 0x20
MOUSEEVENTF_MIDDLEUP = 0x40 
MOUSEEVENTF_RIGHTDOWN = 0x8
MOUSEEVENTF_RIGHTUP = 0x10 
MOUSEEVENTF_MOVE = 0x1class FrontstageMouse():def __init__(self):print('FrontstageMouse init')def bind(self, hwnd):self.hwnd = hwnddef getRelativePosition(self, x, y):left, top, right, bottom = win32gui.GetWindowRect(self.hwnd)return [left + x, top + y]# 前台模拟方法1——使用win32api.mouse_event(默认)  ############################################# 模拟鼠标的按键按下def clickDown(self, x, y, button="l"):win32api.SetCursorPos(self.getRelativePosition(int(x), int(y)))button = button.lower()if button == "l":win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)elif button == "m":win32api.mouse_event(win32con.MOUSEEVENTF_MIDDLEDOWN,0,0,0,0)elif button == "r":win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN,0,0,0,0)print('clickDown x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的按键抬起def clickUp(self, x, y, button="l"):win32api.SetCursorPos(self.getRelativePosition(int(x), int(y)))button = button.lower()if button == "l":win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)elif button == "m":win32api.mouse_event(win32con.MOUSEEVENTF_MIDDLEUP,0,0,0,0)elif button == "r":win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP,0,0,0,0)print('clickUp x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的点击def click(self, x, y, button="l", interval=0.1):win32api.SetCursorPos(self.getRelativePosition(int(x), int(y)))button = button.lower()if button == "l":win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)time.sleep(interval)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)elif button == "m":win32api.mouse_event(win32con.MOUSEEVENTF_MIDDLEDOWN,0,0,0,0)time.sleep(interval)win32api.mouse_event(win32con.MOUSEEVENTF_MIDDLEUP,0,0,0,0)elif button == "r":win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN,0,0,0,0)time.sleep(interval)win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP,0,0,0,0)print('clicked x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的左键双击def doubleClick(self, x, y):win32api.SetCursorPos(self.getRelativePosition(int(x), int(y)))win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)time.sleep(0.05)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)print('doubleClick x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的左键拖动(即在第一个点按下,拖动至第二个点抬起# 但是,不知道为啥,实际上是不准的,滑动的值会比实际的多2倍左右,因此默认除以2# 有时候会误触导致滑动改成点击def slide(self, x1, y1, x2, y2):# win32api.SetCursorPos(self.getRelativePosition(int(x1), int(y1)))time.sleep(0.1)offsetX = int(x2)/2 - int(x1)/2offsetY = int(y2)/2 - int(y1)/2print("offsetX: " + str(offsetX))print("offsetY: " + str(offsetY))win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)time.sleep(0.1)win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, int(offsetX), int(offsetY))time.sleep(0.1)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)print('slide x1: ' + str(x1) + ', y1: ' + str(y1) + ', x2: ' + str(x2) + ', y2: ' + str(y2))# 前台模拟方法2——使用ctypes  ############################################# 模拟鼠标的按键按下def clickDown_2(self, x, y, button="l"):win32api.SetCursorPos(self.getRelativePosition(int(x), int(y)))button = button.lower()if button == "l":windll.user32.mouse_event(MOUSEEVENTF_LEFTDOWN)elif button == "m":windll.user32.mouse_event(MOUSEEVENTF_MIDDLEDOWN)elif button == "r":windll.user32.mouse_event(MOUSEEVENTF_RIGHTDOWN)print('clickDown_2 x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的按键抬起def clickUp_2(self, x, y, button="l"):win32api.SetCursorPos(self.getRelativePosition(int(x), int(y)))button = button.lower()if button == "l":windll.user32.mouse_event(MOUSEEVENTF_LEFTUP)elif button == "m":windll.user32.mouse_event(MOUSEEVENTF_MIDDLEUP)elif button == "r":windll.user32.mouse_event(MOUSEEVENTF_RIGHTUP)print('clickUp_2 x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标左键单击def click_2(self, x, y, button='l', interval=0.05):win32api.SetCursorPos(self.getRelativePosition(int(x), int(y)))button = button.lower()if button == "l":windll.user32.mouse_event(MOUSEEVENTF_LEFTDOWN)time.sleep(interval)windll.user32.mouse_event(MOUSEEVENTF_LEFTUP)elif button == "m":windll.user32.mouse_event(MOUSEEVENTF_MIDDLEDOWN)time.sleep(interval)windll.user32.mouse_event(MOUSEEVENTF_MIDDLEUP)elif button == "r":windll.user32.mouse_event(MOUSEEVENTF_RIGHTDOWN)time.sleep(interval)windll.user32.mouse_event(MOUSEEVENTF_RIGHTUP)print('clicked_2 x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的左键双击def doubleClick_2(self, x, y):win32api.SetCursorPos(self.getRelativePosition(int(x), int(y)))windll.user32.mouse_event(MOUSEEVENTF_LEFTDOWN)time.sleep(0.05)windll.user32.mouse_event(MOUSEEVENTF_LEFTUP)time.sleep(0.05)windll.user32.mouse_event(MOUSEEVENTF_LEFTDOWN)time.sleep(0.05)windll.user32.mouse_event(MOUSEEVENTF_LEFTUP)print('doubleClick_2 x: ' + str(x) + ', y: ' + str(y))def slide_2(self, x1, y1, x2, y2):# win32api.SetCursorPos(self.getRelativePosition(int(x1), int(y1)))time.sleep(0.1)offsetX = int(x2)/2 - int(x1)/2offsetY = int(y2)/2 - int(y1)/2print("offsetX: " + str(offsetX))print("offsetY: " + str(offsetY))win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)time.sleep(0.1)win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, int(offsetX), int(offsetY))time.sleep(0.1)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)print('slide x1: ' + str(x1) + ', y1: ' + str(y1) + ', x2: ' + str(x2) + ', y2: ' + str(y2))

这里使用了两个不同的库分别实现,分别是win32api和ctypes库。win32库实际上也是实现鼠标后台模拟的关键,也可以实现前台模拟,使用mouse_event方法。
其中,win32api中mouse_event的函数原型:
VOID mouse_event(DWORD dwFlags,DWORD dx,DWORD dwFlags,OWORD dx,DWORD dy, DWORD dwData, DWORD dwExtralnfo);
dwFlags:标志位集,指定点击按钮和鼠标动作的多种情况。此参数里的各位可以是下列值的任何合理组合:
MOOSE_EVENTF_ABSOLOTE:表明参数dX,dy含有规范化的绝对坐标。如果不设置此位,参数含有相对数据:相对于上次位置的改动位置。此标志可被设置,也可不设置,不管鼠标的类型或与系统相连的类似于鼠标的设备的类型如何。要得到关于相对鼠标动作的信息,参见下面备注部分。
MOOSEEVENTFMOVE:表明发生移动。
M00SEEVENTF_LEFTDOWN:表明接按下鼠标左键。
M00SEEVENTF_LEFTUP:表明松开鼠标左键。
MOOSEEVENTF_RIGHTDOWN:表明按下鼠标右键。
MOOSEEVENTF_RIGHTUP:表明松开鼠标右键。
MOOSEEVENTF_MIDDLEDOWN:表明按下鼠标中键。
MOOSEEVENTF_MIDDLEUP:表明松开鼠标中键。
MOOSEEVENTF_WHEEL:在Windows NT中如果鼠标有一个轮,表明鼠标轮被移动。移动的数量由dwData给出。
dx:指定鼠标沿x轴的绝对位置或者从上次鼠标事件产生以来移动的数量,依赖于MOOSEEVENTF_ABSOLOTE的设置。给出的绝对数据作为鼠标的实际X坐标;给出的相对数据作为移动的mickeys数。一个mickey表示鼠标移动的数量,表明鼠标已经移动。
dy:指定鼠标沿y轴的绝对位置或者从上次鼠标事件产生以来移动的数量,依赖于MOOSEEVENTF_ABSOLVTE的设置。给出的绝对数据作为鼠标的实际y坐标,给出的相对数据作为移动的mickeys数。
dwData:如果dwFlags为MOOSEEVENTF_WHEEL,则dwData指定鼠标轮移动的数量。正值表明鼠标轮向前转动,即远离用户的方向;负值表明鼠标轮向后转动,即朝向用户。一个轮击定义为WHEEL_DELTA,即120。
如果dwFlagsS不是MOOSEEVENTF_WHEEL,则dWData应为零。
dwExtralnfo:指定与鼠标事件相关的附加32位值。应用程序调用函数GetMessgeExtrajnfo来获得此附加信息。
返回值:无。

后台鼠标模拟

python">import time
import win32api
import win32con
import win32com
import win32gui
import pythoncom
import mathclass BackstageMouse():def __init__(self):print('BackstageMouse init')def bind(self, hwnd):self.hwnd = hwnd# 聚焦句柄对应的窗口def focusHwnd(self):pythoncom.CoInitialize()shell = win32com.client.Dispatch("WScript.Shell")shell.SendKeys('%')win32gui.SetForegroundWindow(self.hwnd)# 后台模拟方法1——使用SendMessage(默认)  ############################################# 模拟鼠标的移动def move(self, x, y):point = win32api.MAKELONG(int(x), int(y))win32api.SendMessage(self.hwnd, win32con.WM_MOUSEMOVE, win32con.MK_LBUTTON, point)# 模拟鼠标的按键按下def clickDown(self, x, y, button="l"):point = win32api.MAKELONG(int(x), int(y))button = button.lower()if button == "l":win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, point)elif button == "m":win32api.SendMessage(self.hwnd, win32con.WM_MBUTTONDOWN, win32con.MK_MBUTTON, point)elif button == "r":win32api.SendMessage(self.hwnd, win32con.WM_RBUTTONDOWN, win32con.MK_RBUTTON, point)print('clickDown x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的按键抬起def clickUp(self, x, y, button="l"):point = win32api.MAKELONG(int(x), int(y))button = button.lower()if button == "l":win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, point)elif button == "m":win32api.SendMessage(self.hwnd, win32con.WM_MBUTTONUP, win32con.MK_MBUTTON, point)elif button == "r":win32api.SendMessage(self.hwnd, win32con.WM_RBUTTONUP, win32con.MK_RBUTTON, point)print('clickUp x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的点击def click(self, x, y, button="l", interval=0.1):point = win32api.MAKELONG(int(x), int(y))button = button.lower()if button == "l":win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, point)time.sleep(interval)win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, point)elif button == "m":win32api.SendMessage(self.hwnd, win32con.WM_MBUTTONDOWN, win32con.MK_MBUTTON, point)time.sleep(interval)win32api.SendMessage(self.hwnd, win32con.WM_MBUTTONUP, win32con.MK_MBUTTON, point)elif button == "r":win32api.SendMessage(self.hwnd, win32con.WM_RBUTTONDOWN, win32con.MK_RBUTTON, point)time.sleep(interval)win32api.SendMessage(self.hwnd, win32con.WM_RBUTTONUP, win32con.MK_RBUTTON, point)print('clicked x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的左键双击def doubleClick(self, x, y):point = win32api.MAKELONG(int(x), int(y))win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONDBLCLK, win32con.MK_LBUTTON, point)win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, point)print('doubleClick x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标移动到坐标,并进行左键单击def moveToPosClick(self, x, y):point = win32api.MAKELONG(int(x), int(y))win32api.SendMessage(self.hwnd, win32con.WM_MOUSEMOVE, win32con.MK_LBUTTON, point)win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, point)win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, point)print('moveToPosClick x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标移动到坐标,并进行左键双击def moveToPosDoubleClick(self, x, y):point = win32api.MAKELONG(int(x), int(y))win32api.SendMessage(self.hwnd, win32con.WM_MOUSEMOVE, win32con.MK_LBUTTON, point)win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONDBLCLK, win32con.MK_LBUTTON, point)win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, point)print('moveToPosDoubleClick x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标使用滚轮向上滚动# 需要聚焦到窗口def wheelUp(self, x, y):self.focusHwnd()point = win32api.MAKELONG(int(x), int(y))win32api.SendMessage(self.hwnd, win32con.WM_MOUSEWHEEL, win32con.WHEEL_DELTA * 5, point)print('wheelDown x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标使用滚轮向下滚动# 需要聚焦到窗口def wheelDown(self, x, y):self.focusHwnd()point = win32api.MAKELONG(int(x), int(y))win32api.SendMessage(self.hwnd, win32con.WM_MOUSEWHEEL, win32con.MK_LBUTTON, point)print('wheelDown x: ' + str(x) + ', y: ' + str(y))# 模拟鼠标的左键拖动(即在第一个点按下,拖动至第二个点抬起)# @step 步长,模拟拖动会将一个操作分开多次来模拟,次数=拖动的长度/步长# @delay 拖动时间,默认0.5秒# @isNeedBtnUp 是否需要弹起鼠标,默认是,若不弹起可通过多次调用实现轨迹拖动def slide(self, x1, y1, x2, y2, isNeedBtnUp=True, step=20, delay=0.5):offsetX = x2-x1offsetY = y2-y1count = int(math.sqrt(offsetX*offsetX + offsetY*offsetY) / step)win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, win32api.MAKELONG(int(x1), int(y1)))for i in range(count):point2 = win32api.MAKELONG(int(x1+offsetX/count*(i+1)), int(y1+offsetY/count*(i+1)))win32api.SendMessage(self.hwnd, win32con.WM_MOUSEMOVE, win32con.MK_LBUTTON, point2)time.sleep(delay/count)if isNeedBtnUp:win32api.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, 0, point2)print('slide x1: ' + str(x1) + ', y1: ' + str(y1) + ', x2: ' + str(x2) + ', y2: ' + str(y2))

这里同样使用win32api的SendMessage方法来实现鼠标的后台模拟,此方法的原型在键盘模拟中提过了,这里不再复述。

使用后台键盘模拟,需要绑定窗口句柄,关于窗口句柄的获取,可以看看下面这篇文章:Python自动化(1)——获取窗口句柄

完整自动化工程代码:https://gitee.com/chj-self/PythonRobotization

大佬们找到问题欢迎拍砖~


http://www.ppmy.cn/news/1470015.html

相关文章

ue 生命周期详解及实例分析

Vue.js 是一个流行的前端框架,它具有丰富的生命周期钩子函数,用于管理组件的创建、挂载、更新和销毁等过程。理解 Vue 生命周期对于开发高质量的 Vue 应用至关重要。本文将深入探讨 Vue 生命周期的各个阶段,并结合实例进行详细分析。 Vue 生命…

Linux常⽤服务器构建-samba

目录 1. 介绍 2. 安装 3. 配置 3.1 创建存放共享⽂件的路径 3.2 创建samba账户 4 重启samba 5. 访问共享⽂件 5.1 mac下访问⽅式 5.2 windows下访问⽅式 1. 介绍 Samba 是在 Linux 和 UNIX 系统上实现 SMB 协议的⼀个免费软件,能够完成在 windows 、 mac 操作系统…

Day07-06_13【CT】LeetCode手撕—1. 两数之和

目录 题目1-思路2- 实现⭐1. 两数之和——题解思路 3- ACM实现 题目 原题连接:1. 两数之和 1-思路 哈希表 利用哈希表存储 key 数组元素值 ——> value 数组下标遍历数组 2- 实现 ⭐1. 两数之和——题解思路 class Solution {public int[] twoSum(int[] nums…

Python项目开发实战:网站图片抓取工具(案例教程)

一、项目背景与需求 随着互联网的发展,网站上的图片资源日益丰富,但有时候我们可能希望将某个网站上的图片批量下载到本地,以便进行后续的分析、处理或备份。因此,开发一个网站图片抓取工具就显得尤为重要。本项目旨在使用Python语言开发一个功能强大、易于使用的网站图片抓…

GPU性能相关的工具

GPU性能相关的工具 GPU的性能测试工具比较多,已知的各个开发厂家是有自己开发的性能测试工具,一般市场上开源或通用的性能测试工具,主要是跑定制的渲染场景,统计平均帧率,经过包装得到跑分值。 整体上可以分成两类&am…

【需求管理】软件需求开发和管理文档(原件Word)

1. 目的 2. 适用范围 3. 参考文件 4. 术语和缩写 5. 需求获取的方式 5.1. 与用户交谈向用户提问题 5.1.1. 访谈重点注意事项 5.1.2. 访谈指南 5.2. 参观用户的工作流程 5.3. 向用户群体发调查问卷 5.4. 已有软件系统调研 5.5. 资料收集 5.6. 原型系统调研 5.6.1. …

云顶之弈-测试报告

一. 项目背景 个人博客系统采用前后端分离的方法来实现,同时使用了数据库来存储相关的数据,同时将其部署到云服务器上。前端主要有四个页面构成:登录页、列表页、详情页以及编辑页,以上模拟实现了最简单的个人博客系统。其结合后…

【前端】Git 常用

文章目录 一、git 配置1.1 查看系统配置1.2 查看当前用户配置1.3 查看当前git用户名1.4 查看当前git邮箱1.5 查看当前仓库配置信息1.6 修改git用户名1.7 修改git邮箱 二、git 常用命令2.1 git init2.2 git clone2.3 git status2.4 git add2.5 git commit2.5 git log2.6 git pul…