修QQ:raw_lines作用域bug+UIA优先生成窗口+剪贴板行数检测
This commit is contained in:
+67
-37
@@ -204,6 +204,33 @@ class MessageMonitor:
|
||||
pass
|
||||
return None
|
||||
|
||||
def _find_qq_window_fresh(self):
|
||||
"""通过类名重新查找 QQ/TIM 窗口,绕过 UIA 缓存(比 ControlFromHandle 更彻底)。"""
|
||||
try:
|
||||
# 先按窗口名称查找
|
||||
for name in ["QQ", "TIM"]:
|
||||
try:
|
||||
w = auto.WindowControl(Name=name)
|
||||
if w.Exists(maxSearchSeconds=0.2):
|
||||
rect = w.BoundingRectangle
|
||||
if rect.width() > 200 and rect.height() > 100:
|
||||
return w
|
||||
except Exception:
|
||||
pass
|
||||
# 按 TXGuiFoundation 类名深度查找
|
||||
root = auto.GetRootControl()
|
||||
for child in root.GetChildren():
|
||||
try:
|
||||
if child.ClassName == "TXGuiFoundation":
|
||||
rect = child.BoundingRectangle
|
||||
if rect.width() > 200 and rect.height() > 100:
|
||||
return child
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
def _force_uia_refresh(self, platform: str):
|
||||
"""通过交互强制窗口更新 UIA 控件树。"""
|
||||
hwnd = self._cached_hwnd.get(platform)
|
||||
@@ -401,6 +428,7 @@ class MessageMonitor:
|
||||
pass
|
||||
|
||||
texts = []
|
||||
raw_lines = [] # 预初始化,防止 content 为空时 UnboundLocalError
|
||||
try:
|
||||
# 确保窗口在前台(失败则返回空,避免发送到错误窗口)
|
||||
# QQ 剪贴板优先路径需要更可靠的前台保证(与发送路径 retries 一致)
|
||||
@@ -793,47 +821,49 @@ class MessageMonitor:
|
||||
def _read_messages(self, window, platform: str = "") -> list:
|
||||
"""每轮重新定位 ListControl。"""
|
||||
if platform == "qq":
|
||||
# QQ NT UIA ListControl 缓存永不更新新消息(返回几天前的旧数据)
|
||||
# 必须剪贴板优先(键盘导航 Enter+Ctrl+End+Ctrl+A/C 读实时消息)
|
||||
# QQ NT: UIA 优先(但重建窗口绕过缓存)+ 剪贴板兜底
|
||||
# 第一步:用新窗口流式重建 UIA 树(不用 ControlFromHandle 缓存)
|
||||
fresh_win = self._find_qq_window_fresh()
|
||||
if fresh_win:
|
||||
texts = self._read_message_list(fresh_win)
|
||||
if texts:
|
||||
return texts
|
||||
texts = self._read_conversation_list(fresh_win)
|
||||
if texts:
|
||||
return texts
|
||||
try:
|
||||
rect = fresh_win.BoundingRectangle
|
||||
boundary = rect.left + rect.width() * 0.40
|
||||
for lst in self._list_controls(fresh_win):
|
||||
try:
|
||||
cr = lst.BoundingRectangle
|
||||
if cr.left >= boundary:
|
||||
texts = self._extract_last_line(lst)
|
||||
if texts:
|
||||
logger.debug(f"[S-C] ListControl(x={cr.left}) → {len(texts)} items")
|
||||
return texts
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
texts = self._collect_filtered_texts(fresh_win, "qq", max_depth=5)
|
||||
if texts:
|
||||
logger.debug(f"[S-D] 全窗文本 → {len(texts)} items")
|
||||
return texts
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 剪贴板兜底:仅当 UIA 完全没读到内容时启用
|
||||
texts = self._read_via_clipboard_once(platform)
|
||||
if texts:
|
||||
# <=5 行的剪贴板很可能是输入框内容(非消息列表)→ 丢弃
|
||||
if texts and len(texts) > 5:
|
||||
return texts
|
||||
texts = self._read_via_clipboard(platform)
|
||||
if texts:
|
||||
if texts and len(texts) > 5:
|
||||
return texts
|
||||
# UIA 兜底:先强制刷新生效,再读取
|
||||
self._force_uia_refresh(platform)
|
||||
self._force_scroll_bottom(platform)
|
||||
time.sleep(0.5)
|
||||
texts = self._read_message_list(window)
|
||||
if texts:
|
||||
return texts
|
||||
texts = self._read_conversation_list(window)
|
||||
if texts:
|
||||
return texts
|
||||
try:
|
||||
rect = window.BoundingRectangle
|
||||
boundary = rect.left + rect.width() * 0.40
|
||||
for lst in self._list_controls(window):
|
||||
try:
|
||||
cr = lst.BoundingRectangle
|
||||
if cr.left >= boundary:
|
||||
texts = self._extract_last_line(lst)
|
||||
if texts:
|
||||
logger.debug(f"[S-C] ListControl(x={cr.left}) → {len(texts)} items")
|
||||
return texts
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
texts = self._collect_filtered_texts(window, "qq", max_depth=5)
|
||||
if texts:
|
||||
logger.debug(f"[S-D] 全窗文本 → {len(texts)} items")
|
||||
return texts
|
||||
except Exception:
|
||||
pass
|
||||
# 最终兜底:win32 文本
|
||||
|
||||
# 最终兜底
|
||||
texts = self._read_win32_texts(platform)
|
||||
if texts:
|
||||
return texts
|
||||
|
||||
Reference in New Issue
Block a user