You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.7 KiB

"""微信窗口定位与基本交互 — 基于 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