PywinAuto UIA后端下定位兄弟元素与子元素的问题
解决Pywinauto UIA后端的兄弟/子元素定位及补丁报错问题
针对你遇到的Pywinauto UIA后端元素定位问题,我来一步步帮你解决:
一、正确定位第一个子元素和下一个兄弟元素
首先要明确:你用dlg4.window(...)得到的是WindowSpecification对象,它是一个查找器,不是实际的UI元素对象。要操作子元素/兄弟元素,需要先把它解析成UIAElementInfo实例,或者用Pywinauto的原生方法:
1. 定位第一个子元素
有两种简单方式:
- 方式一:用
children()方法直接获取第一个元素# 先获取实际的窗口包装对象 target_window = dlg4.window(title='WindowTitleThing', class_name='Text').wrapper_object() # 取第一个子元素的包装对象 first_child = target_window.children()[0] # 如果需要UIA原生元素信息对象 first_child_info = target_window.element_info.first_child() - 方式二:直接通过
element_info访问UIA原生方法target_element_info = dlg4.window(title='WindowTitleThing', class_name='Text').element_info first_child_info = target_element_info.first_child() if first_child_info: # 转成包装对象进行后续操作 first_child_wrapper = first_child_info.wrapper_object()
2. 定位下一个兄弟元素
同样,先拿到实际的UIAElementInfo对象,再调用next_sibling():
target_element_info = dlg4.window(title='WindowTitleThing', class_name='Text').element_info next_sibling_info = target_element_info.next_sibling() if next_sibling_info: next_sibling_wrapper = next_sibling_info.wrapper_object() # 示例:获取兄弟元素的文本 print(next_sibling_wrapper.window_text())
二、修复你的猴子补丁报错问题
你的报错核心原因是:dlg4是WindowSpecification对象(还没完成元素查找),不是UIAElementInfo实例,直接调用first_child(dlg4)会找不到_element属性(这个属性只有UIAElementInfo才有)。另外补丁还有几个小问题,我帮你修正:
修正后的完整补丁代码
import pywinauto from pywinauto import findwindows from pywinauto.uia_element_info import UIAElementInfo from pywinauto.uia_defines import IUIA def first_child(self): print("Getting first child") # 校验输入对象类型,避免传错 if not isinstance(self, UIAElementInfo): raise TypeError("first_child() 仅支持UIAElementInfo类型对象") child = IUIA().iuia.RawViewWalker.GetFirstChildElement(self._element) if child: return UIAElementInfo(child) else: return None def next_sibling(self): print("Getting sibling") if not isinstance(self, UIAElementInfo): raise TypeError("next_sibling() 仅支持UIAElementInfo类型对象") sibling = IUIA().iuia.RawViewWalker.GetNextSiblingElement(self._element) if sibling: return UIAElementInfo(sibling) else: return None def find_first_element(first_only=None, title=None, title_re=None, top_level_only=True, backend=None ): if backend is None: backend = pywinauto.backend.registry.active_backend.name backend_obj = pywinauto.backend.registry.backends[backend] if not top_level_only: raise NotImplementedError("此补丁暂不支持top_level_only=False") rootElement = backend_obj.element_info_class() element = None child = rootElement.first_child() while child is not None: print(f"{child.name} ?= {title}") # 支持精确标题匹配 if title and child.name == title: element = child break # 扩展支持正则标题匹配 elif title_re and title_re.match(child.name): element = child break child = child.next_sibling() return element def new_find_element(**kwargs): if 'first_only' in kwargs and kwargs['first_only'] is True: print("Using patched function to get only the first match") # 移除first_only参数,避免传给原函数引发错误 kwargs.pop('first_only') el = find_first_element(**kwargs) if el is None: raise findwindows.ElementNotFoundError(kwargs) else: return el else: print("Using original function") return findwindows.original_find_element(**kwargs) # 挂载补丁到对应类 UIAElementInfo.first_child = first_child UIAElementInfo.next_sibling = next_sibling findwindows.find_first_element = find_first_element findwindows.original_find_element = findwindows.find_element findwindows.find_element = new_find_element
补丁的正确使用方式
# 初始化UIA后端的桌面对象 d1 = pywinauto.Desktop("uia") # 用补丁的first_only参数快速定位第一个匹配窗口 calc_window = d1.window(first_only=True, title="Calculator").wrapper_object() # 获取窗口的第一个子元素 first_child_info = calc_window.element_info.first_child() # 获取某个子元素的下一个兄弟元素 some_element = calc_window.children()[0].element_info next_sibling_info = some_element.next_sibling()
内容的提问来源于stack exchange,提问作者user2393928
相关产品推荐
相关产品推荐

