2

method of tree viewTree structure of spy++The application I am automating is a win32 supported backend application and using inspect.exe to detect the elements Below is my code trying to click on sales receipt element, on execution I get error

code:screenshot of the treeview in inspect.exe while application image in background

app = Application(backend="win32").connect(process=5468)
app.windows()
dlg = app['TFMenuG.UnicodeClass']
handle = dlg.child_window(control_id='UIA_ButtonControlTypeId (0xC350)').draw_outline()

error:

Traceback (most recent call last):
  File "c:\..\pythonDemo\notepad.py", line 62, in <module>
    handle = dlg.child_window(control_id='UIA_ButtonControlTypeId (0xC350)').draw_outline()
  File "C:\..\AppData\Local\Programs\Python\Python39-32\lib\site-packages\pywinauto\application.py", line 379, in __getattribute__
    ctrls = self.__resolve_control(self.criteria)
  File "C:\..\AppData\Local\Programs\Python\Python39-32\lib\site-packages\pywinauto\application.py", line 261, in __resolve_control
    raise e.original_exception
  File "C:\..\AppData\Local\Programs\Python\Python39-32\lib\site-packages\pywinauto\timings.py", line 436, in wait_until_passes
    func_val = func(*args, **kwargs)
  File "C:\..\AppData\Local\Programs\Python\Python39-32\lib\site-packages\pywinauto\application.py", line 222, in __get_ctrl
    ctrl = self.backend.generic_wrapper_class(findwindows.find_element(**ctrl_criteria))
  File "C:\..\AppData\Local\Programs\Python\Python39-32\lib\site-packages\pywinauto\findwindows.py", line 87, in find_element
    raise ElementNotFoundError(kwargs)
pywinauto.findwindows.ElementNotFoundError: {'control_id': 'UIA_ButtonControlTypeId (0xC350)', 'top_level_only': False, 'parent': <win32_element_info.HwndElementInfo - '', TFMenuG.UnicodeClass, 196780>, 'backend': 'win32'}

Please help me a way to identify the elements. I am doubting the elements are not recognised because of win32 backend

mani
  • 23
  • 6

1 Answers1

2

First, if you use Inspect.exe you must use Application(backend="uia"). If you want to check the application compatibility with older "win32" backend, you need Spy++ which is included into Visual Studio.

Second control_id is integer ID from Spy++ and it can be inconsistent from run to run. I would recommend printing top level window texts by print([w.window_text() for w in app.windows()]) and use necessary text to identify top level window and dump child identifiers:

app.window(title="Main Window Title").dump_tree() # or use title_re for regular expression
app.window(title="Main Window Title").child_window(title="Sales Receipts", control_type="TreeItem").draw_outline().click_input()
# or get .wrapper_object() and discover all available methods,
# wrapper methods can be chained as above

P.S. If Inspect.exe doesn't show property "NativeWindowHandle", it means the element is not visible to "win32" backend.


EDIT1:

Try this code for the "win32" TreeView which is not automatically detected as TreeViewWrapper:

from pywinauto import Application
from pywinauto.controls.common_controls import TreeViewWrapper

app = Application(backend="win32").connect(class_name="TFMenuG.UnicodeClass")
dlg = app['TFMenuG.UnicodeClass']
handle = dlg.child_window(class_name='THTreeView.UnicodeClass').wrapper_object().handle
tree_view = TreeViewWrapper(handle)
print(dir(tree_view)) # list all available methods

tree_view.get_item("Sales Receipts").expand()
tree_view.get_item(r"Sales Receipts\Reports").click(where="text")

When you see all available methods, try documented methods for "win32" TreeView: https://pywinauto.readthedocs.io/en/latest/code/pywinauto.controls.common_controls.html#pywinauto.controls.common_controls.TreeViewWrapper Please note that _treeview_element object returned by get_item(...) represents specific item without window handle, but it's usable.

Vasily Ryabov
  • 9,386
  • 6
  • 25
  • 78
  • 1
    Thanks @VasilyRyabov 1) backend 'Application(backend="uia")' doesnt identify the application. When I try to inspect using spy++ and use code 'app = Application(backend="win32").connect(class_name="TFMenuG.UnicodeClass") app.windows() dlg = app['TFMenuG.UnicodeClass'] handle = dlg.child_window(class_name='THTreeView.UnicodeClass').wrapper_object()' it plrints 'hwndwrapper.HwndWrapper - '', THTreeView.UnicodeClass' – mani May 17 '21 at 06:02
  • While if I try to click on dlg.child_window(class_name='THTreeView.UnicodeClass').click(), it just clicks the first element in the tree which is Sales script, it doesnt show me another property to click on the child elements of the tree. Attaching screenshot of the tree structuer in spy++ in the question. Is there a way to click on the other elements on the tree. Thanks – mani May 17 '21 at 06:31
  • I can suggest way to wrap "win32" element by TreeViewWrapper explicitly. See updated answer. There is no guarantee though. Please let me know if it works. I can add one more regexp to auto detection list by `class_name`. – Vasily Ryabov May 17 '21 at 14:34
  • I tried to `print (tree_view.print_items())` which printed the entire tree structure of each tree view, having all the element name. Also when I try to do tree_view.select("\Sales receipts\Sales")` it highlights Sales under Sales receipt. But when I try to do `tree_view.get_item("\Sales Receipts").expand() tree_view.get_item(r"\Sales receipts\Sales").click(where="Sales")` I get error ` raise RuntimeError("Area ('{}') not found for this tree view item".format(where)) RuntimeError: Area ('Sales') not found for this tree view item`. Unsure what I am missing. Please help. Thanks – – mani May 18 '21 at 07:09
  • Also have added screenshot in the question the methods printed of the tree view which does show click method – mani May 18 '21 at 07:10
  • I found that the tree view gets expanded only when I click on the '+' (to expand and '-' to collapse) sign before the text in the tree structure, Spy++ doesn't identify those signs. OR when I manually double click on the text. `tree_view.get_item("\Sales receipts\Sales").double_click()`doesnt work, throws error `AttributeError: '_treeview_element' object has no attribute 'double_click'` – mani May 19 '21 at 07:17
  • 1
    Got this resolved by selecting the treeview using `tree_view.get_item("\Sales receipts\Sales").get_child("Enter receipt").select()`. Closing this thread – mani May 19 '21 at 09:14
  • `tree_view.get_item("\Sales receipts\Sales\Enter receipt").select()` should work as well. Parameter `where` can have only pre-defined values: "text", "check", "icon" which are different parts of one line item. – Vasily Ryabov May 20 '21 at 11:00