Связывание элементов tabcontrol с диалоговыми окнами? - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь автоматизировать некоторые задачи обслуживания в программном обеспечении ERP. Есть «программы», которые открываются из боковой панели и будут открываться как еще одна вкладка. Проблема в том, что возможно создать несколько экземпляров (вкладок) одной и той же программы. Я хочу убедиться, что когда я запускаю программу, я выбираю правильную вкладку (чтобы убедиться, что на ней нет данных и я не перезаписываю что-то еще). Кажется, я не могу найти способ связать вкладки с диалоговыми окнами, так как они, кажется, находятся на одном уровне в иерархии.

вывод print_control_identifiers:

child_window(title="QAD Enterprise Applications", auto_id="ShellForm", control_type="Window")
   |  
   | TabControl - ''    (L352, T48, R1920, B80)
   | ['TabControl', 'TabControlUser Maintenance', '', '0', '1']
   | child_window(auto_id="920582", control_type="Tab")
   |    |  
   |    | TabItem - 'User Maintenance'    (L354, T53, R479, B79)
   |    | ['User Maintenance', 'TabItem', 'User MaintenanceTabItem', 'User Maintenance0', 'User Maintenance1', 'TabItem0', 'TabItem1', 'User MaintenanceTabItem0', 'User MaintenanceTabItem1']
   |    | child_window(title="User Maintenance", control_type="TabItem")
   |    |  
   |    | TabItem - 'User Maintenance'    (L478, T53, R603, B79)
   |    | ['User Maintenance2', 'TabItem2', 'User MaintenanceTabItem2']
   |    | child_window(title="User Maintenance", control_type="TabItem")
   |    |  
   |    | TabItem - 'User Maintenance'    (L602, T53, R727, B79)
   |    | ['User Maintenance3', 'TabItem3', 'User MaintenanceTabItem3']
   |    | child_window(title="User Maintenance", control_type="TabItem")
   |    |  
   |    | TabItem - 'User Maintenance'    (L726, T53, R851, B80)
   |    | ['User Maintenance4', 'TabItem4', 'User MaintenanceTabItem4']
   |    | child_window(title="User Maintenance", control_type="TabItem")
   |  
   | Pane - ''    (L347, T48, R352, B1027)
   | ['2', 'Pane', 'Pane0', 'Pane1']
   | child_window(auto_id="_splitter", control_type="Pane")
   |  
   | Pane - ''    (L0, T48, R347, B1027)
   | ['3', 'Pane2']
   | child_window(auto_id="pnlSideBarMenu", control_type="Pane")
   |    |  
   |    | Pane - ''    (L0, T48, R347, B1027)
   |    | ['4', 'Pane3']
   |    | child_window(auto_id="pnlSideBar", control_type="Pane")
   |  
   | Pane - ''    (L0, T23, R1920, B48)
   | ['36', 'Pane29']
   | child_window(auto_id="pnlTopHeaderParent", control_type="Pane")
   |    |  
   |    | Pane - ''    (L0, T23, R1920, B48)
   |    | ['37', 'Pane30']
   |    | child_window(auto_id="pnlTopHeader", control_type="Pane")
   |  
   | Pane - ''    (L352, T48, R1920, B1027)
   | ['41', 'Pane32']
   | child_window(auto_id="1182740", control_type="Pane")
   |    |  
   |    | Dialog - 'User Maintenance'    (L352, T80, R1920, B1027)
   |    | ['Dialog2', 'User Maintenance6', 'User MaintenanceDialog', 'User MaintenanceDialog0', 'User MaintenanceDialog1']
   |    | child_window(title="User Maintenance", auto_id="QViewForm", control_type="Window")
   |    |  
   |    | Dialog - 'User Maintenance'    (L352, T80, R1920, B1027)
   |    | ['Dialog3', 'User Maintenance7', 'User MaintenanceDialog2']
   |    | child_window(title="User Maintenance", auto_id="QViewForm", control_type="Window")
   |    |  
   |    | Dialog - 'User Maintenance'    (L352, T80, R1920, B1027)
   |    | ['Dialog4', 'User Maintenance8', 'User MaintenanceDialog3']
   |    | child_window(title="User Maintenance", auto_id="QViewForm", control_type="Window")
   |    |  
   |    | Dialog - 'User Maintenance'    (L352, T80, R1920, B1027)
   |    | ['Dialog5', 'User Maintenance9', 'User MaintenanceDialog4']
   |    | child_window(title="User Maintenance", auto_id="QViewForm", control_type="Window")
   | 

Таким образом, я могу контролировать и выбирать вкладки с помощью элемента TabControl «User Maintenance», и я могу изменять содержимое в диалоге «User Maintenance», но я не могу найти ничего, что связывает их вместе.

Я пробовал некоторые вещи, такие как циклическое переключение вкладок и возвращение индекса активной вкладки:

tabctrl = wnd.child_window(control_type='Tab')
idx = 0
for t in tabctrl.iter_children():
    if (t.window_text() == 'User Maintenance'):
        t.select()
        break
    else:
        idx += 1

tab_handle = pane.children()[idx].handle

pane = wnd.child_window(class_name='WindowsForms10.MDICLIENT.app.0.2004eee', control_type='Pane')
tab = pane.child_window(handle=tab_handle, control_type="Window", title='User Maintenance')

Но индексы tabctrl.children () и pane.children () совершенно не связаны. Я знаю это, потому что вот область, которую я пытаюсь изменить:

username_field = tab.child_window(auto_id="usr_userid", control_type="Pane").child_window(auto_id="_textBox", control_type="Edit")
username_field.set_text(username)

он введет текст в правильное поле, но в другом диалоговом окне.

Я думаю, что я, возможно, достиг предела pywinauto, учитывая, что именно так была разработана программа, но я все еще думаю, что возможен обходной путь, но я не уверен, как этого достичь: Когда меню открывается, оно порождает окно и фокусирует его. Я просто хочу сделать некоторые проверки в ожидании открытия окна и в ожидании фокусировки на клавиатуре (программа может быть очень медленной или очень быстрой в разы), но я не могу понять, как выбрать дочерний диалог без указания на первый взгляд случайный дескриптор (я попытался перебрать все вкладки и посмотреть, помечены ли там различные свойства как «включенные», «видимые», «активные»). Вот вывод идентификатора элемента управления для диалогового окна, я просто не знаю, как провести различие между любым из диалогов.

Dialog - 'User Maintenance'    (L352, T80, R1920, B1027)
['Dialog', 'User Maintenance', 'User MaintenanceDialog']
child_window(title="User Maintenance", auto_id="QViewForm", control_type="Window")
   |  
   | Pane - ''    (L352, T80, R1918, B1027)
   | ['', 'Pane', '0', '1', 'Pane0', 'Pane1']
   | child_window(auto_id="_dtApplication", control_type="Pane")
   |    |  
   |    | Pane - ''    (L352, T110, R1918, B1027)
   |    | ['2', 'Pane2']
   |    | child_window(auto_id="DTApplication_Fill_Panel", control_type="Pane")
   |    |    |  
   |    |    | Pane - ''    (L352, T110, R1124, B182)
   |    |    | ['3', 'Pane3']
   |    |    | child_window(auto_id="_dtWindow0", control_type="Pane")
   |    |    |    |  
   |    |    |    | Pane - ''    (L352, T110, R1123, B182)
   |    |    |    | ['4', 'Pane4']
   |    |    |    | child_window(auto_id="461788", control_type="Pane")
   |    |    |    |    |  
   |    |    |    |    | GroupBox - ' '    (L352, T110, R1120, B182)
   |    |    |    |    | [' ', ' GroupBox', 'GroupBox', 'GroupBox0', 'GroupBox1']
   |    |    |    |    | child_window(title=" ", auto_id="_framePanel", control_type="Group")
   |    |    |    |    |    |  
   |    |    |    |    |    | Pane - ''    (L356, T126, R1119, B181)
   |    |    |    |    |    | ['5', 'Pane5']
   |    |    |    |    |    | child_window(auto_id="_frameGroup", control_type="Pane")
   |    |    |    |    |    |    |  
   |    |    |    |    |    |    | Edit - '  User ID: '    (L357, T132, R418, B153)
   |    |    |    |    |    |    | ['6', 'Edit', 'Edit0', 'Edit1']
   |    |    |    |    |    |    | child_window(title="  User ID: ", auto_id="_label", control_type="Edit")
   |    |    |    |    |    |    |    |  
   |    |    |    |    |    |    |    | Edit - ''    (L357, T132, R418, B153)
   |    |    |    |    |    |    |    | ['7', 'Edit2']
   |    |    |    |    |    |    |  
   |    |    |    |    |    |    | Pane - ''    (L418, T132, R543, B153)
   |    |    |    |    |    |    | ['8', 'Pane6']
   |    |    |    |    |    |    | child_window(auto_id="usr_userid", control_type="Pane")
   |    |    |    |    |    |    |    |  
   |    |    |    |    |    |    |    | Edit - ''    (L418, T132, R543, B153)
   |    |    |    |    |    |    |    | ['9', 'Edit3']
   |    |    |    |    |    |    |    | child_window(auto_id="_textBox", control_type="Edit")

Резюме: я пытаюсь выбрать auto_id="_textBox", control_type="Edit", но в любое время может быть открыто более 3 диалогов этого окна, и я не могу узнать, какой из них выбран.

Edit: Я заметил, что при смене вкладок кажется, что одно из этих значений меняется на отрицательное:

>>> pane.children(title='User Maintenance') 
[<uiawrapper.UIAWrapper - 'User Maintenance', Dialog, 141765657>, <uiawrapper.UIAWrapper - 'User Maintenance', Dialog, -1460376553>]
>>> pane.children(title='User Maintenance') 
[<uiawrapper.UIAWrapper - 'User Maintenance', Dialog, -1460376553>, <uiawrapper.UIAWrapper - 'User Maintenance', Dialog, 141765657>] 

Что это за идентификатор, если не дескриптор?

Edit2: я нашел решение, которое работает, но я уверен, что должен быть лучший способ.

tab_handle = pane.children()[0].element_info._get_current_handle()
tab = pane.child_window(handle=tab_handle)

Кажется, что _get_current_handle () всегда работает для целевой вкладки, независимо от того, какой элемент в списке я выберу. Это, безусловно, работает на данный момент - учитывая, что, если кто-нибудь знает немного более элегантный способ, я бы хотел знать.

...