windowSpecification类
首先介绍一下,pywinauto对于窗口的操作,一般需要借助于windowSpecification类;
这个类的对象用于记录一组搜索条件,通过这些条件来查找窗口或者控件,一个windowSpecification对象会在每次执行操作时根据条件匹配对应的Wrapper Object进行操作;
magic_loopup是pywinauto进行匹配的模式,大多时候不需要精确的条件就可以匹配到准确的目标,所以指定的搜索条件不能匹配到合适的窗口时,程序并不会立刻报错,只有当需要利用windowSpec操作窗口时,错误才会发生;
- 窗口的树形结构
这个可以通过inspect看出,程序的窗口和子窗口以及控件,形成了一个树形结构,这个参考上一篇文章的inspect简单介绍;
windowSpecification类里也提供了一系列方法获取树形结构种的各级元素,见下文介绍;
元素定位
参数打印
- window.print_control_identifiers(depth=None,filename=None)
- dump_tree(depth=None,filename=None)
depth:输出层数,可以指定输出的层级
filename:直接将结果保存为文件,如果指定文件名,那么控制台就不会再输出结果,而会把结果输出保存至文件中
这两种方法均可:
- 打印当前WindowSpec所匹配元素为根节点的所有子节点及其详细信息;
- 为每个节点提供了child_window()的调用方法实例
- 为每个节点提供了使用【】调用的定位信息
输出示例:
关键字参数定位
- class_name:类名
- title:控件的标题,print_control_identifiers会直接打印,对应inspect就是name属性
- control_type:inspect对应LocalizedControlType属性
- auto_id:inspect中的automationId属性
- control_id/control_type
一般我用这些参数属性都能基本定位,其余一些不常用属性,列举一下:
- title_re:title的正则匹配
- best_match:模糊匹配title
- framework_id,ctrl_index等等
定位语法
窗口对话框:window[窗口名或者类名]
或者app.window(title=")关键字参数定位
控件定位:window[“窗口名”][“控件名”]
或者app.window().child_window()关键字参数定位
以下为打印出的元素以及属性使用:
定位元素的一些问题处理
一些右击鼠标才会出现的菜单项目控件定位异常
目前暂未解决,但目前针对使用找到了一个解决方法。
右击鼠标出现的菜单项目与主窗口并列,为单独的窗口,一开始使用了DeskTop切换主窗口与弹出的菜单项目进程;
pywinauto.Desktop(backend='uia').window(class_name='QMenu', title='...')
但是只有在第一次打开软件后定位成功,后续再次定位失败,原因可能是弹出菜单是动态创建的,每次打开都生成了一个新的句柄;
有以下解决方法:
1、使用等待机制(见后续说明),确保弹出菜单的句柄和属性稳定后再次定位,尝试后偶尔可以偶尔失败;
2、使用上一层级的窗口定位,但是我定位的窗口是一个独立窗口,无上一层级;
3、使用其他属性关键字定位,这个也没有用;
最后,我是直接在菜单弹出后,使用键盘输入TAB键,直接操作菜单,目前是满足我的操作需求的:
from pywinauto.keyboard import SendKeys
SendKeys('{TAB}''{TAB}''{TAB}''{TAB}''{TAB}''{ENTER}')
后续如果有了更好的解决办法再补充
定位不止一个控件
可能同一关键字参数会有多个元素使用,比如子窗口title,以及子窗口下的button的title等,会有重复,这种情况下可能会报错,提示定位到不止一个元素;
这里可以添加多个关键字参数进行定位即可;
window.child_window(title='GO',auto_id="")
控件操作()
查看控件方法(dir(控件.wrapper_object()))
-
dir:不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表
语法:dir([object]),object为对象、变量、类
dir():返回值为模块的属性列表
dir([]):返回值为列表的方法 -
wrapper_object()
用于获取该windowSpec对象所匹配的具体窗口/控件的wrapper_object,wrapper object的类型由匹配的具体控件决定,例如ToolbarWrapper/ButtonWrapper/ListViewWrapper等;
对于具体控件的操作,其实是由相应的wrapper object调用来实现的,pywinauto需要获取相应的wrapper object才能操作控件,pywinauto是隐藏了对它的调用的,以精简代码
例如:缩小窗口这个操作
dlg.wrapper_object().minimize()
隐藏wrapper object是相同的操作
dlg.minimize()
综合以上,可以直接使用print(dir(控件.wrapper_object()))打印出控件可操作的方法
下一部分再来看一下各种控件的不同类型所能使用的一些方法,举例:
以上,add这个控件的wrapper object的类型是uia_controls.ButtonWrapper
不同控件类型能使用的方法说明
不同控件能使用的方法官方说明
或者直接在pywinauto中查看原方法函数的代码(ctrl+鼠标左键 点击该方法)