如何使用Python自动控制windows桌面


Posted in Python onJuly 11, 2019

前言

在使用PC时与PC交互的主要途径是看屏幕显示、听声音,点击鼠标和敲键盘等等。在自动化办公的趋势下,繁琐的工作可以让程序自动完成。比如自动化测试、自动下单交易等。很多软件除了可以GUI方式操作外还可以用CLI接口操作,不过当一些软件未提供CLI接口时,我们应该怎么办呢?我们还可以用程序控制桌面上的窗口、模拟点击鼠标或按下键盘等动作来释放自己。

pywin32是一个Python库,它为Python提供访问Windows API的扩展,提供了齐全的windows常量、接口、线程以及COM机制等等,安装后会自带一个pythonwin的IDE。接下来主要介绍下如何通过Python去操作windows桌面软件。

1、打开软件或文件

比如打开一个谷歌浏览器,或者打开一个word文件,如下所示:

win32api.ShellExecute(1, 'open',
 r'C:Program Files (x86)GoogleChromeApplicationchrome.exe',
 '', '', 1)
win32api.ShellExecute(1, 'open',
 r'C:UsersJayDesktopEnvironment Guider.docx',
 '', '', 1)

win32api.ShellExecute()的参数主要包括:

  • HWND:指定父窗口句柄
  • Operation:指定动作, 譬如"edit",“explore”,“open”,“find”,“print”,“NULL”
  • FileName:指定要打开的文件或程序
  • Parameters:指定打开程序所需参数
  • Directory:缺省目录
  • ShowCmd:打开选项,可选值:
    • SW_HIDE = 0; {隐藏窗口,活动状态给令一个窗口}
    • SW_SHOWNORMAL = 1; {用最近的大小和位置显示窗口, 同时令其进入活动状态}
    • SW_NORMAL = 1; {用当前的大小和位置显示一个窗口,不改变活动窗口}
    • SW_SHOWMINIMIZED = 2; {最小化窗口,并将其激活}
    • SW_SHOWMAXIMIZED = 3; {最大化窗口,并将其激活}
    • SW_MAXIMIZE = 3; {同 SW_SHOWMAXIMIZED}
    • SW_SHOWNOACTIVATE = 4; {用最近的大小和位置显示一个窗口,不改变活动窗口}
    • SW_SHOW = 5; {用当前的大小和位置显示一个窗口,令其进入活动状态}
    • SW_MINIMIZE = 6; {最小化窗口, 不激活}
    • SW_SHOWMINNOACTIVE = 7; {同 SW_MINIMIZE}
    • SW_SHOWNA = 8; {用当前的大小和位置显示一个窗口,不改变活动窗口}
    • SW_RESTORE = 9; {同 SW_SHOWNORMAL}
    • SW_SHOWDEFAULT = 10; {同 SW_SHOWNORMAL}
    • SW_MAX = 10; {同 SW_SHOWNORMAL}

执行成功会返回应用程序句柄, 如果返回值 <= 32,则表示执行错误。返回值可能的错误有:

  • 0—— {内存不足}
  • 2—— {文件名错误}
  • 3—— {路径名错误}
  • 11—— {EXE 文件无效}
  • 26—— {发生共享错误}
  • 27—— {文件名不完全或无效}
  • 28—— {超时}
  • 29—— {DDE 事务失败}
  • 30—— {正在处理其他 DDE 事务而不能完成该 DDE 事务}
  • 31—— {没有相关联的应用程序}

2、查找窗体的句柄

在win32编程的世界里,包括窗口到文本框的所有控件都是窗体,所有的窗体都有独立的句柄。要操作任意一个窗体,都需要找到这个窗体的句柄。句柄是一个32位整数,在windows中用于标记对象。比如查找Snipping Tool和New Text Document.txt的句柄,如下所示:

para_hld = win32gui.FindWindow(None, "Snipping Tool")# 1836416
para_hld = win32gui.FindWindow(None, "New Text Document.txt - Notepad")# 591410

win32gui.FindWindow()属于win32gui的模块,它自顶层窗口(也就是桌面)开始搜索条件匹配的窗体,并返回这个窗体的句柄。该函数仅能查找主窗口,因此无法搜索子窗口,也不区分大小写,未找到则返回0。

win32gui.FindWindow()的参数主要包括 (lpClassName=None, lpWindowName=None):

  • lpClassName:字符型,窗体的类名,可以在Spy++里找到
  • lpWindowName:字符型,窗口名,也就是标题栏上能看见的那个标题。

如何使用Python自动控制windows桌面

3、查找句柄的类名和标题

比如通过Snipping Tool和New Text Document.txt的句柄查找对应的类名和标题,如下所示:

title = win32gui.GetWindowText(1836416)
classname = win32gui.GetClassName(1836416)
print "windows handler:{0}; title:{1}; classname:{2}".format(1836416, title, classname)

打印显示如下:

windows handler:1836416; title:Snipping Tool; classname:Microsoft-Windows-Tablet-SnipperToolbar
title = win32gui.GetWindowText(591410)
classname = win32gui.GetClassName(591410)
print "windows handler:{0}; title:{1}; classname:{2}".format(591410, title, classname)

打印显示如下:

windows handler:591410; title:New Text Document.txt - Notepad; classname:Notepad

4、调用win32gui.EnumWindows()枚举所有窗口句柄

直到最后一个顶层窗口被枚举则停止枚举过程。如下所示:

hWndList = []
win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), hWndList)
print hWndList
for hwnd in hWndList:
 title = win32gui.GetWindowText(hwnd)
 print title

打印显示如下:

[852802L, 65946L, 65928L, 65930L, 65900L, 65920L, 65924L, 65922L, 65944L, 65892L, 65886L, 6817870L, 65960L, 6031410L, …… 66052L, 65734L]
……
New Text Document.txt - Notepad
Snipping Tool
DDE Server Window
OfficePowerManagerWindow
OfficePowerManagerWindow
DDE Server Window
GDI+ Window
Global Internet Access
……

5、win32gui.SetForegroundWindow()函数将指定窗体设置到最顶层,并且激活该窗口

构造函数为:win32gui.SetWindowPos(HWN hWnd,HWND hWndlnsertAfter, int X,int Y, int cx,int cy, UNIT.Flags)

关于win32gui.SetForegroundWindow(para_hld)报错的问题:

pywintypes.error: (0, ‘SetForegroundWindow', ‘No error message is available')

其实调用SetForegroundWindow()会有很多限制,参考官网的说明

如何使用Python自动控制windows桌面

因此调用SetForegroundWindow()时需要查看当前运行的条件是否符合上述要求,此处在调用SetForegroundWindow()前事先发送一个键盘event来解决该问题。

例程如下所示:

win32api.keybd_event(13, 0, 0, 0) #
win32gui.SetForegroundWindow(para_hld)

6、win32api.keybd_event()模拟键盘输入

构造函数如下所示:

win32api.keybd_event (bVk, bScan, dwFlags, dwExtraInfo)
  • bVk:虚拟键码(键盘键码对照表见附录);
  • bScan:硬件扫描码,一般设置为0即可;
  • dwFlags:函数操作的一个标志位,如果值为KEYEVENTF_EXTENDEDKEY则该键被按下,也可设置为0即可,如果值为KEYEVENTF_KEYUP则该按键被释放;
  • dwExtraInfo:定义与击键相关的附加的32位值,一般设置为0即可。

按下enter键后抬起的例程如下所示:

win32api.keybd_event(13,0,0,0) # enter
win32api.keybd_event(13,0,win32con.KEYEVENTF_KEYUP,0) #释放按键

7、模拟鼠标输入

直接给出例程,如下所示:

# 获取鼠标当前位置的坐标
print win32api.GetCursorPos()
# 将鼠标移动到坐标处
win32api.SetCursorPos((100, 100))
# 左点击
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 100, 100, 0, 0)
time.sleep(2)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 100, 100, 0, 0)

8、关于鼠标键盘的操作还可以使用PyUserInput库

PyUserInput是一个使用python的跨平台的操作鼠标和键盘的模块,使用非常方便。支持的平台及依赖如下:

  • Linux - Xlib
  • Mac - Quartz, AppKit
  • Windows - pywin32, pyHook

实例化一个鼠标和键盘对象,如下所示:

from pymouse import PyMouse
from pykeyboard import PyKeyboard
m = PyMouse()
k = PyKeyboard()
操作鼠标和键盘,如下所示:
m.click(190,70,1)#移动并且在xy位置点击
time.sleep(2)
m.click(190, 200, 1)#移动并且在xy位置点击
time.sleep(2)
k.tap_key(k.function_keys[5])#?点击功能键F5

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
实践Python的爬虫框架Scrapy来抓取豆瓣电影TOP250
Jan 20 Python
浅谈python函数之作用域(python3.5)
Oct 27 Python
Python编程pygal绘图实例之XY线
Dec 09 Python
numpy自动生成数组详解
Dec 15 Python
python实现对文件中图片生成带标签的txt文件方法
Apr 27 Python
浅谈tensorflow中几个随机函数的用法
Jul 27 Python
django项目搭建与Session使用详解
Oct 10 Python
Python第三方Window模块文件的几种安装方法
Nov 22 Python
对Python协程之异步同步的区别详解
Feb 19 Python
Puppeteer使用示例详解
Jun 20 Python
详解Python绘图Turtle库
Oct 12 Python
python从PDF中提取数据的示例
Oct 30 Python
python字典嵌套字典的情况下找到某个key的value详解
Jul 10 #Python
如何安装并使用conda指令管理python环境
Jul 10 #Python
python变量的存储原理详解
Jul 10 #Python
python中 * 的用法详解
Jul 10 #Python
通过python实现随机交换礼物程序详解
Jul 10 #Python
Python实现简单的列表冒泡排序和反转列表操作示例
Jul 10 #Python
Python获取好友地区分布及好友性别分布情况代码详解
Jul 10 #Python
You might like
PHP CURL CURLOPT参数说明(curl_setopt)
2013/09/30 PHP
CodeIgniter使用phpcms模板引擎
2013/11/12 PHP
浅谈PHP中Stream(流)
2015/06/08 PHP
Zend Framework教程之响应对象的封装Zend_Controller_Response实例详解
2016/03/07 PHP
php通过两层过滤获取留言内容的方法
2016/07/11 PHP
php如何获取Http请求
2020/04/30 PHP
Webkit的跨域安全问题说明
2011/09/13 Javascript
基于BootStrap Metronic开发框架经验小结【六】对话框及提示框的处理和优化
2016/05/12 Javascript
JS限定手机版中图片大小随分辨率自动调整的方法
2016/12/05 Javascript
javascript中递归的两种写法
2017/01/17 Javascript
JS对象和字符串之间互换操作实例分析
2019/02/02 Javascript
解决layui的input独占一行的问题
2019/09/10 Javascript
javascript 内存模型实例详解
2020/04/18 Javascript
解决vue请求接口第一次成功,第二次失败问题
2020/09/08 Javascript
JavaScript实现网页留言板功能
2020/11/23 Javascript
js实现随机点名功能
2020/12/23 Javascript
vue3.0中友好使用antdv示例详解
2021/01/05 Vue.js
python中xrange和range的区别
2014/05/13 Python
Python编程使用tkinter模块实现计算器软件完整代码示例
2017/11/29 Python
Python爬虫爬取一个网页上的图片地址实例代码
2018/01/16 Python
Python简单计算给定某一年的某一天是星期几示例
2018/06/27 Python
Flask核心机制之上下文源码剖析
2018/12/25 Python
python 实现敏感词过滤的方法
2019/01/21 Python
Python3 解决读取中文文件txt编码的问题
2019/12/20 Python
python打包多类型文件的操作方法
2020/09/21 Python
ReVive利维肤美国官网:RéVive Skincare
2018/04/18 全球购物
Java提供了哪些企业应用编程接口
2015/02/13 面试题
电气个人求职信范文
2014/02/04 职场文书
村委会换届选举方案
2014/05/03 职场文书
冬季安全检查方案
2014/05/23 职场文书
抗洪救灾感谢信
2015/01/22 职场文书
南京南京观后感
2015/06/02 职场文书
甲午风云观后感
2015/06/02 职场文书
2019大学毕业晚会主持词
2019/06/21 职场文书
使用Html+Css实现简易导航栏功能(导航栏遇到鼠标切换背景颜色)
2021/04/07 HTML / CSS
Python编程中内置的NotImplemented类型的用法
2022/03/23 Python