"""微信窗口定位与基本交互 — 基于 uiautomation""" from __future__ import annotations import logging import time import uiautomation as uia from ..config import Config logger = logging.getLogger(__name__) class WeChatWindow: """封装微信主窗口的查找、激活、以及子面板获取""" def __init__(self, config: Config) -> None: self.config = config self._window: uia.WindowControl | None = None # ------------------------------------------------------------------ # 公开方法 # ------------------------------------------------------------------ def find_window(self) -> uia.WindowControl | None: """查找微信主窗口(不激活)""" try: win = uia.WindowControl( searchDepth=1, Name=self.config.wechat_title, ClassName="WeChatMainWndForPC", ) if win.Exists(maxSearchSeconds=2): self._window = win logger.info("找到微信窗口: %s", win.Name) return win except Exception: logger.debug("通过 ClassName 查找失败,尝试按标题查找") win = uia.WindowControl( searchDepth=1, Name=self.config.wechat_title, ) if win.Exists(maxSearchSeconds=2): self._window = win logger.info("找到微信窗口: %s", win.Name) return win logger.warning("未找到微信窗口") self._window = None return None def activate(self) -> bool: """激活(前置)微信窗口""" win = self._window or self.find_window() if win is None: return False try: win.SetFocus() time.sleep(0.3) return True except Exception: logger.exception("激活微信窗口失败") return False def get_window(self) -> uia.WindowControl | None: return self._window def is_alive(self) -> bool: """窗口是否仍然存在""" win = self._window if win is None: return False try: return win.Exists(maxSearchSeconds=1) except Exception: return False def get_chat_panel(self) -> uia.Control | None: """获取当前聊天消息列表面板""" win = self._window or self.find_window() if win is None: return None # 聊天消息区域通常在 "ChatPanel" 或包含消息列表的 ListControl try: # 微信 PC 版的消息列表一般是一个 ListControl,ClassName 包含 "ChatMsgList" panel = win.ListControl(searchDepth=8) if panel.Exists(maxSearchSeconds=2): return panel except Exception: logger.debug("通过 ListControl 查找聊天面板失败") # 备选方案:搜索名称包含 "消息" 的控件 try: panel = win.ListControl(Name="消息", searchDepth=8) if panel.Exists(maxSearchSeconds=1): return panel except Exception: pass logger.warning("未找到聊天消息面板") return None def get_conversation_list_panel(self) -> uia.Control | None: """获取左侧会话列表面板""" win = self._window or self.find_window() if win is None: return None try: # 会话列表通常在左侧,ClassName 包含 "SessionList" panel = win.ListControl(searchDepth=8) if panel.Exists(maxSearchSeconds=2): return panel except Exception: pass logger.warning("未找到会话列表面板") return None