"""诊断:dump TIM 窗口控件树,找消息区路径""" import sys import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import uiautomation as auto import win32gui import logging logging.basicConfig(level=logging.INFO, format="%(message)s") log = logging.getLogger("debug") OUTPUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "tim_dump.txt") def find_tim_window(): """找 TIM 主窗口(TXGuiFoundation 类名)""" root = auto.GetRootControl() for child in root.GetChildren(): try: cn = child.ClassName or "" name = child.Name or "" rect = child.BoundingRectangle if cn == "TXGuiFoundation" and rect.width() > 200 and rect.height() > 100: log.info(f"找到 TIM: Name={name} ClassName={cn} rect=({rect.left},{rect.top},{rect.right},{rect.bottom})") return child except: pass # 也试试 "TIM" 名称 try: w = auto.WindowControl(Name="TIM") if w.Exists(maxSearchSeconds=0.5): log.info(f"找到 TIM(ByName): {w.Name} ClassName={w.ClassName}") return w except: pass return None def dump_tree(ctrl, depth=0, max_depth=5, file=None): """递归 dump 控件树""" if depth > max_depth: return indent = " " * depth try: cn = ctrl.ControlTypeName or "?" name = (ctrl.Name or "")[:80] cls = ctrl.ClassName or "" rect = ctrl.BoundingRectangle has_scroll = False try: sp = ctrl.GetScrollPattern() has_scroll = sp is not None except: pass line = f"{indent}{cn} Class={cls} Name=\"{name}\" rect=({rect.left},{rect.top},{rect.right},{rect.bottom}) scroll={has_scroll}" if file: file.write(line + "\n") else: print(line) except Exception as e: line = f"{indent}[error] {e}" if file: file.write(line + "\n") else: print(line) return try: for child in ctrl.GetChildren(): dump_tree(child, depth + 1, max_depth, file) except: pass def dump_flat_texts(window, max_depth=6): """模拟 _collect_all_texts 的输出""" texts = [] def walk(ctrl, depth): if depth > max_depth: return try: cr = ctrl.BoundingRectangle if cr.width() < 20 or cr.height() < 20: return except: pass try: name = ctrl.Name if name and name.strip(): texts.append((depth, name.strip()[:100])) except: pass try: for child in ctrl.GetChildren(): walk(child, depth + 1) except: pass try: for child in ctrl.GetChildren(): walk(child, 1) except: pass return texts def main(): print("=" * 60) print("TIM 控件树诊断") print("=" * 60) win = find_tim_window() if not win: print("未找到 TIM 窗口") return hwnd = win.NativeWindowHandle print(f"\nHWND: {hwnd}") print(f"ClassName: {win.ClassName}") print(f"Name: {win.Name}") print() # 1. 深度 4 级控件树 print("-" * 60) print("控件树 (depth<=4):") print("-" * 60) with open(OUTPUT, "w", encoding="utf-8") as f: f.write("TIM 控件树诊断\n") f.write(f"HWND={hwnd} ClassName={win.ClassName} Name={win.Name}\n\n") f.write("--- 控件树 (depth<=4) ---\n") dump_tree(win, 0, 4, f) # 2. 当前 _collect_all_texts 抓到的全部文本 print("\n" + "-" * 60) print("全窗深度遍历文本 (depth<=6):") print("-" * 60) all_texts = dump_flat_texts(win, 6) with open(OUTPUT, "a", encoding="utf-8") as f: f.write("\n--- 全窗文本 (depth<=6) ---\n") for d, t in all_texts: f.write(f" d={d} \"{t}\"\n") for d, t in all_texts: print(f" d={d} \"{t}\"") # 3. 找 ListControl print("\n" + "-" * 60) print("ListControl 列表:") print("-" * 60) def find_list(ctrl, depth=0, max_d=8): if depth > max_d: return try: if ctrl.ControlTypeName == "ListControl": name = (ctrl.Name or "")[:60] rect = ctrl.BoundingRectangle print(f" depth={depth} Name=\"{name}\" rect=({rect.left},{rect.top},{rect.right},{rect.bottom})") # dump items for item in ctrl.GetChildren(): try: iname = (item.Name or "")[:80] irec = item.BoundingRectangle print(f" item: \"{iname}\" rect=({irec.left},{irec.top},{irec.right},{irec.bottom})") except: pass except: pass try: for child in ctrl.GetChildren(): find_list(child, depth + 1, max_d) except: pass with open(OUTPUT, "a", encoding="utf-8") as f: f.write("\n--- ListControl ---\n") find_list(win) # 4. 找所有 Text 或 Edit 控件(搜索框特征) print("\n" + "-" * 60) print("EditControl / 搜索框:") print("-" * 60) def find_edit(ctrl, depth=0, max_d=8): if depth > max_d: return try: ct = ctrl.ControlTypeName or "" if "Edit" in ct or "Text" in ct: name = (ctrl.Name or "")[:60] cls = ctrl.ClassName or "" rect = ctrl.BoundingRectangle print(f" depth={depth} type={ct} class={cls} Name=\"{name}\" rect=({rect.left},{rect.top},{rect.right},{rect.bottom})") with open(OUTPUT, "a", encoding="utf-8") as f: f.write(f" depth={depth} type={ct} class={cls} Name=\"{name}\"\n") except: pass try: for child in ctrl.GetChildren(): find_edit(child, depth + 1, max_d) except: pass find_edit(win, 0, 8) print(f"\n完整诊断已保存到: {OUTPUT}") print("请把该文件内容发给我分析") if __name__ == "__main__": main()