技术经验解读:【python自动化】02.pywin32库自动操作键鼠(保姆级代码注释)

简介: 技术经验解读:【python自动化】02.pywin32库自动操作键鼠(保姆级代码注释)

目录


源码和工具下载


大漠综合工具->坐标和窗口信息抓取


在你的桌面上新建一个记事本用于后面的代码测试


完整项目源码


实现思路


介绍win32的基础思路


基本步骤


API介绍


代码实战


1. 获取窗口句柄的三种方法


2. 根据窗口句柄获取窗口信息


3. 通过句柄设置窗口


4. 激活窗口


5. 鼠标信息的获取


6. 鼠标点击事件


7. 键盘键位操作


8. 延时等待


9. 剪切板操作


10. 消息框与选择问答


11. 关闭窗口


N. 小结


总结


『python自动化』分享win32gui、cv2、easyocr等库相关的新手入门教程,目标是编写python程序进行自动化办公,解放双手。


欢迎关注 『python自动化』 系列,持续更新中


欢迎关注 『python自动化』 系列,持续更新中


如果安装win32gui库遇到了困难,可以参考下文安装。


【python自动化】01.安装配置库和环境之win32gui安装失败(保姆级图文)


源码和工具下载


大漠综合工具->坐标和窗口信息抓取


大漠综合工具获取句柄和窗口信息


1.用十字标记拖动到需要的窗口(注意拖到大窗口而不是小窗口,是整个记事本窗口而不是记事本的输入区域的小窗口)


2.绑定(方便后续的操作)


3.点击属性即可查看窗口信息,包括窗口的大小、坐标、16进制句柄


我的gitee仓库pywin32库自动操作键鼠


我们一般用的是16进制句柄,在这里查看


坐标和色点采集


注意这里的相对坐标和绝对坐标,我们绑定了窗口后默认把窗口左上角(0,0)视为参考标准。


在你的桌面上新建一个记事本用于后面的代码测试


完整项目源码


下载拿来即用


我的gitee仓库pywin32库自动操作键鼠


实现思路


介绍win32的基础思路


万物皆是窗口,首先获取窗口的句柄,然后再以此为基础对于窗口输送键鼠的命令。


基本步骤


获取窗口句柄->激活窗口->设置窗口大小位置->激活聊天输入框->输入内容


API介绍


下面的代码实战会详细介绍每个方法的参数,也可以访问pywin32的官方文档查看。(建议这么做,因为以后我们自学其他库都要经历查看文档这个过程)


官网网址


代码实战


1. 获取窗口句柄的三种方法


注意窗口类名, 窗口标题名两者必须至少有一个才能找到你想要的窗口,另一个可以缺省为None


法1:win32gui.FindWindow(窗口类名, 窗口标题名)#直接查找窗口


实例:win32gui.FindWindow(“Notepad”, None)


返回值:窗口的16进制句柄


import win32gui


#如果失败,要做好异常处理


#1.根据窗口标题获取句柄,通过标题查找,仅返回一个顶层窗口的句柄,不支持模糊查询


try:


# 获取窗口句柄


handle = win32gui.FindWindow("Notepad", None)#通过窗口标题获取窗口句柄


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


法2:win32gui.FindWindowEx(父窗口句柄, 查找窗口顺序, 窗口类名, 窗口标题名)#根据父窗口查找子窗口


实例:win32gui.FindWindowEx(0, 0, “Notepad”, None)


父窗口句柄:如果为 0,则假定为桌面窗口


查找窗口顺序:子窗口后按Z顺序搜索,可以为0搜索全部


返回值:查找得到的子窗口窗口的16进制句柄


#2.通过父窗口找子窗口,根据窗口类名和标题检索句柄,查找


# 参数


# 家长:PyHANDLE


# 将搜索其子窗口的窗口。如果为 0,则假定为桌面窗口。


# ChildAfter : PyHANDLE


# 子窗口后按Z顺序搜索,可以为0搜索全部


# 类名:PyResourceId


# 要查找的窗口类的名称或原子,可以是 None


# 窗口名称:字符串


# 要查找的窗口标题,可以是 None


import win32gui


try:


# 获取窗口句柄


# handle = win32gui.FindWindowEx(0, 0, "Notepad", '新建文本文档.txt - 记事本')


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)


#注意,当你修改了记事本后标题名字前加上了一个变成了“新建文本文档.txt - 记事本”,所以这里可以填写None缺省,只用类名查找


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


法3:win32gui.WindowFromPoint((窗口x坐标, 窗口y坐标))#根据窗口坐标查找顶层符合坐标要求的一个窗口


实例:win32gui.WindowFromPoint((0, 0))


窗口坐标是每个窗口都会有的属性,但是这个方法只会查找顶层的那一个窗口,所以说改变置顶窗口就会改变通过这个方法获取的窗口句柄,所以不建议用。


返回值:查找得到的子窗口窗口的16进制句柄


#3.根据窗口左上角坐标获取句柄,(0, 0)只获取最顶层的左上角窗口,这种方法我个人不建议使用,因为顶层的窗口变化了,句柄就变化了


import win32gui


try:


# 获取窗口句柄


handle = win32gui.WindowFromPoint((0, 0))


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


2. 根据窗口句柄获取窗口信息


#获取窗口信息 (x,y坐标,还有宽度,高度)


原型:win32gui.GetWindowRect(窗口句柄)


实例:handleMessage = //代码效果参考:http://hnjlyzjd.com/hw/wz_24417.html

win32gui.GetWindowRect(handle)

返回值:handleMessage是一个元组,包含四个元素,结构是(x坐标,y坐标,宽度,高度)


#获取窗口标题


原型:win32gui.GetWindowText(窗口句柄)


实例:win32gui.GetWindowText(handle)


返回值:字符串,窗口标题


#获取窗口类名


原型:win32gui.GetClassName(窗口句柄)


实例:win32gui.GetClassName(handle)


返回值:字符串,窗口类名


import win32gui


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


# 注意窗口信息获取如果失败,要做好异常处理


try:


# 获取窗口信息 (x,y坐标,还有宽度,高度)


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


# 获取窗口标题


title = win32gui.GetWindowText(handle)


print("窗口标//代码效果参考:http://hnjlyzjd.com/hw/wz_24415.html

题是:{}".format(title))

# 获取窗口类名


class_name = win32gui.GetClassName(handle)


print("窗口类名是:{}".format(class_name))


except Exception as e:


print("窗口信息获取失败:{}".format(e))


3. 通过句柄设置窗口


#设置窗口信息


原型:win32gui.MoveWindow(窗口句柄, 窗口左边界,窗口上边界,窗口宽度,窗口高度,确定窗口是否被刷新)


实例:win32gui.MoveWindow(handle, 0, 0, 1280, 768, True)


返回值:None


import win32gui


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


try:


# 获取窗口信息 (x,y坐标,还有宽度,高度)


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


# 获取窗口标题


title = win32gui.GetWindowText(handle)


print("窗口标题是:{}".format(title))


# 获取窗口类名


class_name = win32gui.GetClassName(handle)


print("窗口类名是:{}".format(class_name))


# 设置窗口


# 参数:句柄,窗口左边界,窗口上边界,窗口宽度,窗口高度,确定窗口是否被刷新


win32gui.MoveWindow(handle, 0, 0, 1280, 768, True)


# 设置窗口后获取窗口信息,查看是否设置成功


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("修改窗口后的窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


except Exception as e:


print("窗口信息获取失败:{}".format(e))


4. 激活窗口


#激活窗口


原型:win32gui.SetForegroundWindow(窗口句柄)


实例:win32gui.SetForegroundWindow(handle)


返回值:None


import win32gui


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


# 将创建指定窗口的线程设置到前台,并且激活该窗口


win32gui.SetForegroundWindow(handle)


except Exception as e:


print("窗口句柄获取失败或是前台设置失败:{}".format(e))


5. 鼠标信息的获取


#获取鼠标位置


原型:win32api.GetCursorPos()


实例:point_position = win32api.GetCursorPos()


返回值:point_position 是一个元组,结构是(x坐标,y坐标)


#设置鼠标位置


原型:win32api.SetCursorPos((x坐标,y坐标))


实例:win32api.SetCursorPos((0, 0))


返回值:None


import win32gui


import win32api


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


# 获取鼠标位置


point_position = win32api.GetCursorPos()


print("鼠标位置是:{}".format(point_position))


# 设置鼠标位置


win32api.SetCursorPos((0, 0))


# 获取鼠标位置


point_position = win32api.GetCursorPos()


print("设置后鼠标位置是:{}".format(point_position))


except Exception as e:


print("窗口句柄获取失败或是前台设置失败:{}".format(e))


6. 鼠标点击事件


鼠标点击分为点击和弹起2个过程。


#按下鼠标左键


原型:win32api.mouse_event(键位操作, 0, 0)


实例:win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)


返回值:None


#松开鼠标左键


原型:win32api.mouse_event(键位操作, 0, 0)


实例:win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)


参数解读(dwFlags ,dx ,dy ,dwData ,dwExtraInfo)


dwFlags=0:双字,指定各种功能选项的标志


dx:double类型,鼠标的水平位置


dy : double类型,鼠标的垂直位置


dwData:double类型,标志特定参数


dwExtraInfo=0:double类型,与鼠标事件相关的附加数据


返回值:None


#键位表


MOUSEEVENTF_LEFTDOWN:表明接按下鼠标左键


MOUSEEVENTF_LEFTUP:表明松开鼠标左键


MOUSEEVENTF_RIGHTDOWN:表明按下鼠标右键


MOUSEEVENTF_RIGHTUP:表明松开鼠标右键


MOUSEEVENTF_MIDDLEDOWN:表明按下鼠标中键


MOUSEEVENTF_MIDDLEUP:表明松开鼠标中键


MOUSEEVENTF_WHEEL:鼠标轮移动,数量由data给出


import win32api


import win32con


import win32gui


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


# 获取鼠标位置


point_position = win32api.GetCursorPos()


print("鼠标位置是:{}".format(point_position))


# 模拟鼠标在(1000, 500)位置进行点击操作


point = (1000, 500)


win32api.SetCursorPos(point)


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)#按下鼠标左键


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)#松开鼠标左键


# 获取鼠标位置


point_position = win32api.GetCursorPos()


print("鼠标位置是:{}".format(point_position))


except Exception as e:


print("窗口句柄获取失败或是前台设置失败:{}".format(e))


7. 键盘键位操作


键盘操作类似鼠标也分为按下和弹起2个过程。


有所区别的是,如果要输入内容,要先让鼠标激活输入框的焦点,所以要先点击一下。


同时也要注意一点,窗口操作最好加入一些延时,避免时序错误,导致出现先输入再激活焦点的错误,从而导致无法输入。


#按下按键


原型:win32api.keybd_event(键码, 硬件扫描码, 按下还是弹起的标志位, 与击键相关的附加的32位值)


实例:win32api.keybd_event(65, 0, KEYEVENTF_EXTENDEDKEY, 0)#按下A


实例:win32api.keybd_event(65, 0, 0, 0)#按下A


返回值:None


#弹起按键


原型:win32api.keybd_event(键码, 硬件扫描码, 按下还是弹起的标志位, 与击键相关的附加的32位值)


实例:win32api.keybd_event(65, 0, win32con.KEYEVENTF_KEYUP, 0)#松开A


实例:win32api.keybd_event(65, 0, 1, 0)#松开A


返回值:None


bVk:虚拟键码


bScan:硬件扫描码,一般设置为0即可


dwFlags:函数操作的一个标志位,如果值为KEYEVENTF_EXTENDEDKEY则该键被按下,也可设置为0即可,如果值为KEYEVENTF_KEYUP(也就是1)则该按键被释放


dwExtraInfo:定义与击键相关的附加的32位值,一般设置为0即可


import win32gui


import win32api


import win32con


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#桌面窗口的所有子窗口检索类名"Edit",标题为None的窗口


print("窗口句柄是:{}".format(handle))


# 设置窗口


# 参数:句柄,窗口左边界,窗口上边界,窗口宽度,窗口高度,确定窗口是否被刷新


win32gui.MoveWindow(handle, 0, 0, 500, 500, True)


# 设置窗口后获取窗口信息,查看是否设置成功


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("修改窗口后的窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


# 将创建指定窗口的线程设置到前台,并且激活该窗口


win32gui.SetForegroundWindow(handle)


#加入延时,否则可能会操作失败


print("如果没有下面以这一行代码,可能无法正常输入A B 字母,这就是延时等待的作用")


win32api.Sleep(1000)


#激活窗口输入栏


# 模拟鼠标在(246,217)位置进行点击操作,这个坐标主要是点击一下txt记事本的输入窗口,激活焦点


point = (246,217)


win32api.SetCursorPos(point)


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)#按下鼠标左键


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)#松开鼠标左键


#加入延时,否则可能会操作失败


win32api.Sleep(1000)


#在记事本中输入A B 字母


win32api.keybd_event(65, 0, 0, 0)#按下A


win32api.keybd_event(66, 0, 0, 0)#按下B


win32api.keybd_event(65, 0, win32con.KEYEVENTF_KEYUP, 0)#松开A


win32api.keybd_event(66, 0, win32con.KEYEVENTF_KEYUP, 0)#松开B


except Exception as e:


print("窗口句柄获取失败或是前台设置失败:{}".format(e))


8. 延时等待


这一节的内容和第7节类似,就是让大家试试看,如果不加入延时会发生什么,强调一下延时的作用。


#延时等待


原型:win32api.Sleep(等待毫秒)


实例:win32api.Sleep(1000)


返回值:None


import win32gui


import win32api


import win32con


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#桌面窗口的所有子窗口检索类名"Edit",标题为None的窗口


print("窗口句柄是:{}".format(handle))


# 设置窗口


# 参数:句柄,窗口左边界,窗口上边界,窗口宽度,窗口高度,确定窗口是否被刷新


win32gui.MoveWindow(handle, 0, 0, 500, 500, True)


# 设置窗口后获取窗口信息,查看是否设置成功


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("修改窗口后的窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


# 将创建指定窗口的线程设置到前台,并且激活该窗口


win32gui.SetForegroundWindow(handle)


#加入延时,否则可能会操作失败


print("如果没有下面以这一行代码,可能无法正常输入A B 字母,这就是延时等待的作用")


win32api.Sleep(1000)


#激活窗口输入栏


# 模拟鼠标在(246,217)位置进行点击操作


point = (246,217)


win32api.SetCursorPos(point)


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)#按下鼠标左键


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)#松开鼠标左键


#加入延时,否则可能会操作失败


print("如果没有下面以这一行代码,可能无法正常输入A B 字母,这就是延时等待的作用")


win32api.Sleep(1000)


#在记事本中输入A B 字母


win32api.keybd_event(65, 0, 0, 0)#按下A


win32api.keybd_event(66, 0, 0, 0)#按下B


win32api.keybd_event(65, 0, win32con.KEYEVENTF_KEYUP, 0)#松开A


win32api.keybd_event(66, 0, win32con.KEYEVENTF_KEYUP, 0)#松开B


except Exception as e:


print("错误:{}".format(e))


9. 剪切板操作


#打开剪切板


原型:win32clipboard.OpenClipboard()


实例:win32clipboard.OpenClipboard()


返回值:None


#剪切板置空


原型:win32clipboard.EmptyClipboard()


实例:win32clipboard.EmptyClipboard()


置剪切板为空,赋初始值是程序员的好习惯,注意任何数据一开始的样子


返回值:None


相关文章
|
14天前
|
调度 开发者 Python
Python中的异步编程:理解asyncio库
在Python的世界里,异步编程是一种高效处理I/O密集型任务的方法。本文将深入探讨Python的asyncio库,它是实现异步编程的核心。我们将从asyncio的基本概念出发,逐步解析事件循环、协程、任务和期货的概念,并通过实例展示如何使用asyncio来编写异步代码。不同于传统的同步编程,异步编程能够让程序在等待I/O操作完成时释放资源去处理其他任务,从而提高程序的整体效率和响应速度。
|
8天前
|
运维 监控 安全
运维自动化:提升效率与可靠性的关键技术
在信息技术飞速发展的今天,企业对IT系统的稳定性和高效性要求越来越高。运维自动化作为实现这一目标的重要手段,通过软件工具来模拟、执行和管理IT运维任务,不仅大幅提高了工作效率,还显著增强了系统的可靠性。本文将探讨运维自动化的概念、实施步骤以及面临的挑战,旨在为读者提供一份关于如何有效实施运维自动化的指南。
|
9天前
|
运维 监控 Python
自动化运维:使用Python脚本简化日常任务
【10月更文挑战第36天】在数字化时代,运维工作的效率和准确性成为企业竞争力的关键。本文将介绍如何通过编写Python脚本来自动化日常的运维任务,不仅提高工作效率,还能降低人为错误的风险。从基础的文件操作到进阶的网络管理,我们将一步步展示Python在自动化运维中的应用,并分享实用的代码示例,帮助读者快速掌握自动化运维的核心技能。
23 3
|
11天前
|
数据库 Python
异步编程不再难!Python asyncio库实战,让你的代码流畅如丝!
在编程中,随着应用复杂度的提升,对并发和异步处理的需求日益增长。Python的asyncio库通过async和await关键字,简化了异步编程,使其变得流畅高效。本文将通过实战示例,介绍异步编程的基本概念、如何使用asyncio编写异步代码以及处理多个异步任务的方法,帮助你掌握异步编程技巧,提高代码性能。
29 4
|
11天前
|
API 数据处理 Python
探秘Python并发新世界:asyncio库,让你的代码并发更优雅!
在Python编程中,随着网络应用和数据处理需求的增长,并发编程变得愈发重要。asyncio库作为Python 3.4及以上版本的标准库,以其简洁的API和强大的异步编程能力,成为提升性能和优化资源利用的关键工具。本文介绍了asyncio的基本概念、异步函数的定义与使用、并发控制和资源管理等核心功能,通过具体示例展示了如何高效地编写并发代码。
23 2
|
15天前
|
运维 监控 应用服务中间件
自动化运维:如何利用Python脚本提升工作效率
【10月更文挑战第30天】在快节奏的IT行业中,自动化运维已成为提升工作效率和减少人为错误的关键技术。本文将介绍如何使用Python编写简单的自动化脚本,以实现日常运维任务的自动化。通过实际案例,我们将展示如何用Python脚本简化服务器管理、批量配置更新以及监控系统性能等任务。文章不仅提供代码示例,还将深入探讨自动化运维背后的理念,帮助读者理解并应用这一技术来优化他们的工作流程。
|
9天前
|
数据采集 数据可视化 数据挖掘
利用Python进行数据分析:Pandas库实战指南
利用Python进行数据分析:Pandas库实战指南
|
13天前
|
Web App开发 测试技术 数据安全/隐私保护
自动化测试的魔法:使用Python进行Web应用测试
【10月更文挑战第32天】本文将带你走进自动化测试的世界,通过Python和Selenium库的力量,展示如何轻松对Web应用进行自动化测试。我们将一起探索编写简单而强大的测试脚本的秘诀,并理解如何利用这些脚本来确保我们的软件质量。无论你是测试新手还是希望提升自动化测试技能的开发者,这篇文章都将为你打开一扇门,让你看到自动化测试不仅可行,而且充满乐趣。
|
1月前
|
机器学习/深度学习 人工智能 运维
构建高效运维体系:从自动化到智能化的演进
本文探讨了如何通过自动化和智能化手段,提升IT运维效率与质量。首先介绍了自动化在简化操作、减少错误中的作用;然后阐述了智能化技术如AI在预测故障、优化资源中的应用;最后讨论了如何构建一个既自动化又智能的运维体系,以实现高效、稳定和安全的IT环境。
65 4
|
1月前
|
运维 Linux Apache
,自动化运维成为现代IT基础设施的关键部分。Puppet是一款强大的自动化运维工具
【10月更文挑战第7天】随着云计算和容器化技术的发展,自动化运维成为现代IT基础设施的关键部分。Puppet是一款强大的自动化运维工具,通过定义资源状态和关系,确保系统始终处于期望配置状态。本文介绍Puppet的基本概念、安装配置及使用示例,帮助读者快速掌握Puppet,实现高效自动化运维。
52 4