Files
msgbot/debug_tim.py
T
youpaishidifu 4349b5c176 清理旧代码+修复TIM抓错搜索框
- 删除旧 _collect_all_texts(被 _collect_filtered_texts 替代)
- 删除 _read_message_list_deep(旧QQ路径,已废弃)
- 微信fallback改走 _collect_filtered_texts
- 添加 _click_message_area:剪贴板前先点击中右区域聚焦消息区
- TIM Electron 通过鼠标点击消息区再Ctrl+A→Ctrl+C
- 添加 win32api import(用于 SetCursorPos+mouse_event)
2026-07-24 23:34:20 +08:00

207 lines
6.2 KiB
Python

"""诊断: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()