技术经验解读:【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


相关文章
|
20天前
|
搜索推荐 Python
使用Python自动化生成物业通知单
本文介绍如何使用Python结合Pandas和python-docx库自动化生成物业通知单。通过读取Excel数据并填充至Word模板,实现高效准确的通知单批量制作。包括环境准备、代码解析及效果展示,适用于物业管理场景。
58 14
|
23天前
|
数据采集 数据可视化 数据挖掘
利用Python自动化处理Excel数据:从基础到进阶####
本文旨在为读者提供一个全面的指南,通过Python编程语言实现Excel数据的自动化处理。无论你是初学者还是有经验的开发者,本文都将帮助你掌握Pandas和openpyxl这两个强大的库,从而提升数据处理的效率和准确性。我们将从环境设置开始,逐步深入到数据读取、清洗、分析和可视化等各个环节,最终实现一个实际的自动化项目案例。 ####
|
23天前
|
开发框架 数据建模 中间件
Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器是那些静悄悄的幕后英雄。它们不张扬,却能默默地为函数或类增添强大的功能。本文将带你了解装饰器的魅力所在,从基础概念到实际应用,我们一步步揭开装饰器的神秘面纱。准备好了吗?让我们开始这段简洁而富有启发性的旅程吧!
31 6
|
10天前
|
JSON 数据可视化 测试技术
python+requests接口自动化框架的实现
通过以上步骤,我们构建了一个基本的Python+Requests接口自动化测试框架。这个框架具有良好的扩展性,可以根据实际需求进行功能扩展和优化。它不仅能提高测试效率,还能保证接口的稳定性和可靠性,为软件质量提供有力保障。
34 7
|
16天前
|
数据可视化 Python
以下是一些常用的图表类型及其Python代码示例,使用Matplotlib和Seaborn库。
通过这些思维导图和分析说明表,您可以更直观地理解和选择适合的数据可视化图表类型,帮助更有效地展示和分析数据。
57 8
|
23天前
|
API Python
【Azure Developer】分享一段Python代码调用Graph API创建用户的示例
分享一段Python代码调用Graph API创建用户的示例
46 11
|
25天前
|
测试技术 Python
探索Python中的装饰器:简化代码,增强功能
在Python的世界中,装饰器是那些能够为我们的代码增添魔力的小精灵。它们不仅让代码看起来更加优雅,还能在不改变原有函数定义的情况下,增加额外的功能。本文将通过生动的例子和易于理解的语言,带你领略装饰器的奥秘,从基础概念到实际应用,一起开启Python装饰器的奇妙旅程。
35 11
|
20天前
|
Python
探索Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器就像是给函数穿上了一件神奇的外套,让它们拥有了超能力。本文将通过浅显易懂的语言和生动的比喻,带你了解装饰器的基本概念、使用方法以及它们如何让你的代码变得更加简洁高效。让我们一起揭开装饰器的神秘面纱,看看它是如何在不改变函数核心逻辑的情况下,为函数增添新功能的吧!
|
21天前
|
程序员 测试技术 数据安全/隐私保护
深入理解Python装饰器:提升代码重用与可读性
本文旨在为中高级Python开发者提供一份关于装饰器的深度解析。通过探讨装饰器的基本原理、类型以及在实际项目中的应用案例,帮助读者更好地理解并运用这一强大的语言特性。不同于常规摘要,本文将以一个实际的软件开发场景引入,逐步揭示装饰器如何优化代码结构,提高开发效率和代码质量。
44 6
|
25天前
|
Android开发 开发者 Python
通过标签清理微信好友:Python自动化脚本解析
微信已成为日常生活中的重要社交工具,但随着使用时间增长,好友列表可能变得臃肿。本文介绍了一个基于 Python 的自动化脚本,利用 `uiautomator2` 库,通过模拟用户操作实现根据标签批量清理微信好友的功能。脚本包括环境准备、类定义、方法实现等部分,详细解析了如何通过标签筛选并删除好友,适合需要批量管理微信好友的用户。
34 7