pywinauto操作–定位控件

控件分类

桌⾯应⽤程序客⼾端的控件和层级结构是GUI⾃动化测试的基础。理解控件的分类、特性和层级关系,能够帮助测试⼈员更⾼效地定位和操作控件,实现⾃动化测试。在实际测试中,结合控件的属性和事件,可以编写灵活且可靠的测试脚本。

打开UI对象检查⼯具UI Spy,通过ControlType可查看所定位到控件的类型。

通过合理的分类和说明,可以更清晰地理解控件的功能和⽤途,便于在GUI⾃动化测试中进⾏操作和定位。

在使⽤ pywinauto 进⾏⾃动化操作时,程序启动后,⾸先需要定位到⽬标窗⼝。窗⼝是所有控件的容器,只有成功定位到窗⼝,才能进⼀步操作窗⼝内的控件。控件是窗⼝功能的具体体现,包括按钮、⽂本框、列表等,对控件的操作是⾃动化任务的核⼼。然⽽,在对控件进⾏操作之前,必须先完成控件的定位。定位控件是确保操作准确性的关键步骤,也是⾃动化流程的基础。接下来,我们将深⼊学习如何⾼效定位控件。

定位控件,需要借助前⾯学到的 print_control_identifiers() ⽅法,打印窗⼝及其⼦控件的标识符信息

Dialog - '"untitled • - Sublime Text (UNREGISTERED)" • - Sublime Text (UNREGISTERED)'    (L0, T0, R0, B0)
['Dialog', '"untitled • - Sublime Text (UNREGISTERED)" • - Sublime Text (UNREGISTERED)Dialog', '"untitled • - Sublime Text (UNREGISTERED)" • - Sublime Text (UNREGISTERED)']
child_window(title=""untitled • - Sublime Text (UNREGISTERED)" • - Sublime Text (UNREGISTERED)", control_type="Window")
   | 
   | ScrollBar - ''    (L-32000, T-32100, R-31900, B-32090)
   | ['ScrollBar', 'ScrollBar0', 'ScrollBar1']
   |    | 
   |    | Button - '左移一列'    (L0, T0, R0, B0)
   |    | ['Button', '左移一列', '左移一列Button', 'Button0', 'Button1']
   |    | child_window(title="左移一列", auto_id="UpButton", control_type="Button")
   |    | 
   |    | Thumb - '位置'    (L0, T0, R0, B0)
   |    | ['位置Thumb', '位置', 'Thumb', '位置Thumb0', '位置Thumb1', '位置0', '位置1', 'Thumb0', 'Thumb1']
   |    | child_window(title="位置", auto_id="ScrollbarThumb", control_type="Thumb")
   |    | 
   |    | Button - '右移一列'    (L0, T0, R0, B0)
   |    | ['Button2', '右移一列', '右移一列Button']
   |    | child_window(title="右移一列", auto_id="DownButton", control_type="Button")
   | 
   | ScrollBar - ''    (L-32100, T-32000, R-32090, B-31900)
   | ['ScrollBar2']
   |    | 
   |    | Button - '上一行'    (L0, T0, R0, B0)
   |    | ['上一行Button', 'Button3', '上一行']
   |    | child_window(title="上一行", auto_id="UpButton", control_type="Button")
   |    | 
   |    | Thumb - '位置'    (L0, T0, R0, B0)
   |    | ['位置Thumb2', '位置2', 'Thumb2']
   |    | child_window(title="位置", auto_id="ScrollbarThumb", control_type="Thumb")
   |    | 
   |    | Button - '下一行'    (L0, T0, R0, B0)
   |    | ['Button4', '下一行', '下一行Button']
   |    | child_window(title="下一行", auto_id="DownButton", control_type="Button")
   | 
   | TitleBar - ''    (L-31955, T-31997, R-31699, B-31950)
   | ['TitleBar']
   |    | 
   |    | Menu - '系统'    (L-31987, T-31987, R-31943, B-31943)
   |    | ['系统Menu', '系统', 'Menu', '系统0', '系统1', 'Menu0', 'Menu1']
   |    | child_window(title="系统", auto_id="MenuBar", control_type="MenuBar")
   |    |    | 
   |    |    | MenuItem - '系统'    (L-31987, T-31987, R-31943, B-31943)
   |    |    | ['MenuItem', '系统2', '系统MenuItem', 'MenuItem0', 'MenuItem1']
   |    |    | child_window(title="系统", control_type="MenuItem")
   |    | 
   |    | Button - '还原'    (L-31978, T-31999, R-31884, B-31950)
   |    | ['Button5', '还原', '还原Button']
   |    | child_window(title="还原", control_type="Button")
   |    | 
   |    | Button - '最大化'    (L-31884, T-31999, R-31792, B-31950)
   |    | ['Button6', '最大化', '最大化Button']
   |    | child_window(title="最大化", control_type="Button")
   |    | 
   |    | Button - '关闭'    (L-31792, T-31999, R-31698, B-31950)
   |    | ['Button7', '关闭', '关闭Button']
   |    | child_window(title="关闭", control_type="Button")
   | 
   | Menu - '应用程序'    (L-31987, T-31987, R-30387, B-31949)
   | ['应用程序', '应用程序Menu', 'Menu2']
   | child_window(title="应用程序", auto_id="MenuBar", control_type="MenuBar")
   |    | 
   |    | MenuItem - 'File'    (L-31987, T-31942, R-31920, B-31904)
   |    | ['MenuItem2', 'FileMenuItem', 'File']
   |    | child_window(title="File", control_type="MenuItem")
   |    | 
   |    | MenuItem - 'Edit'    (L-31920, T-31942, R-31849, B-31904)
   |    | ['MenuItem3', 'EditMenuItem', 'Edit']
   |    | child_window(title="Edit", control_type="MenuItem")
   |    | 
   |    | MenuItem - 'Selection'    (L-31849, T-31942, R-31716, B-31904)
   |    | ['MenuItem4', 'SelectionMenuItem', 'Selection']
   |    | child_window(title="Selection", control_type="MenuItem")
   |    | 
   |    | MenuItem - 'Find'    (L-31716, T-31942, R-31639, B-31904)
   |    | ['MenuItem5', 'Find', 'FindMenuItem']
   |    | child_window(title="Find", control_type="MenuItem")
   |    | 
   |    | MenuItem - 'View'    (L-31639, T-31942, R-31556, B-31904)
   |    | ['MenuItem6', 'ViewMenuItem', 'View']
   |    | child_window(title="View", control_type="MenuItem")
   |    | 
   |    | MenuItem - 'Goto'    (L-31556, T-31942, R-31471, B-31904)
   |    | ['MenuItem7', 'Goto', 'GotoMenuItem']
   |    | child_window(title="Goto", control_type="MenuItem")
   |    | 
   |    | MenuItem - 'Tools'    (L-31471, T-31942, R-31382, B-31904)
   |    | ['MenuItem8', 'Tools', 'ToolsMenuItem']
   |    | child_window(title="Tools", control_type="MenuItem")
   |    | 
   |    | MenuItem - 'Project'    (L-31382, T-31942, R-31274, B-31904)
   |    | ['MenuItem9', 'ProjectMenuItem', 'Project']
   |    | child_window(title="Project", control_type="MenuItem")
   |    | 
   |    | MenuItem - 'Preferences'    (L-31274, T-31942, R-31111, B-31904)
   |    | ['MenuItem10', 'PreferencesMenuItem', 'Preferences']
   |    | child_window(title="Preferences", control_type="MenuItem")
   |    | 
   |    | MenuItem - 'Help'    (L-31111, T-31942, R-31029, B-31904)
   |    | ['MenuItem11', 'Help', 'HelpMenuItem']
   |    | child_window(title="Help", control_type="MenuItem")

动态解析

基于best_match标题来定位

⽰例1:定位sublime Text⼯具的菜单栏

child_window

child_window() 和定位窗⼝的⽅法 window() 参数⼀样,可以通过标题或者类名进⾏精确匹配、模糊匹配等,在这⾥额外拓展⼏个进⾏控件定位时需要⽤到的参数:

# win.print_control_identifiers()

# 定位控件
# 方法一:best_match

# 获取应用程序
# proc=win.应用程序
# proc.wait("visible")

# 方法二:child_window
# win.child_window(title="应用程序")

# bar=win.child_window(class_name="ScrollBar",found_index=1)
# bar.print_control_identifiers()

# proc=win.child_window(auto_id="MenuBar",found_index=0)
# proc.print_control_identifiers()

# 定位file菜单项
# file_menu=win.child_window(auto_id="Item5")
# file_menu.print_control_identifiers()

# ele=win.window(title="nihaowoshisana")

# 根据file控件找父控件
# file_menu=win.child_window(title="File",control_type="MenuItem")
# file_parent=file_menu.parent()
# print(file_parent)

# 根据父控件,找到所有的子控件
# proc_menu=win.child_window(title="应用程序", auto_id="MenuBar", control_type="MenuBar")
# print(proc_menu.children())

app=Application(backend="uia").connect(process=14536)
win=app.window(title="QQMusic")

win.wait("visible")

group=app.window(auto_id="QQMusic.background.body.bodyRight.controlBox.play2",control_type="Group")
group.wait("visible")

btn=group.window(auto_id="QQMusic.background.body.bodyRight.controlBox.play2.addLocal",control_type="Button")
btn.wait("visble")

💡 Tips:

控件之间存在⽗⼦关系,可通过 children() ⽅法获取控件的⼦类,也可通过parent() ⽅法获取控件的⽗类

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐