class MonitorApp:
def __init__(self):
self.running = True
- self.monitoring = False
+ START_MONITORING = config.getboolean("General", "start_monitoring", fallback=False)
+ self.monitoring = START_MONITORING
# hash 监测模式状态
self.hash_mode = False
self._last_login_hash = None
self._user_resized = False
self._resend_link_sent = False
+ self._last_logged_msg = ""
self._last_logged_status = ""
self._setup_ui()
self.root.after(100, self._main_loop_tick)
self.root.bind("<Configure>", self._on_window_configure)
+ # 同步UI到初始监控状态
+ if self.monitoring:
+ self.toggle_btn.config(text="停用监控", bg="#4CAF50", fg="white")
+ self._set_status("监控运行中")
+ log.info("监控已启用")
# ── info dialog ──
def _show_info(self):
# ── status ──
def _set_status(self, text):
self.status_var.set(text)
- if text != self._last_logged_status:
- log.info("状态: %s", text)
- self._last_logged_status = text
self._update_window_width()
+ def _log_state(self, level, msg):
+ """去重日志:连续相同消息不重复记录"""
+ if msg != self._last_logged_msg:
+ if level == "info":
+ log.info("%s", msg)
+ elif level == "warn":
+ log.warning("%s", msg)
+ elif level == "error":
+ log.error("%s", msg)
+ self._last_logged_msg = msg
+
+ def _is_wechat_foreground(self):
+ """检查微信是否在前端(活跃窗口),是则不打断用户操作"""
+ try:
+ fg_hwnd = win32gui.GetForegroundWindow()
+ wechat_wins = _find_wechat_windows()
+ for w in wechat_wins:
+ if hasattr(w, '_hWnd') and w._hWnd == fg_hwnd:
+ return True
+ except Exception:
+ pass
+ return False
+
def _update_window_width(self):
if self._user_resized:
return # 用户已手动调整窗口,不再自动调整
self.root.destroy()
log.info("程序退出")
- def _is_wechat_foreground(self):
- """检查微信是否在前端(活跃窗口),是则不打断用户操作"""
- try:
- fg_hwnd = win32gui.GetForegroundWindow()
- wechat_wins = _find_wechat_windows()
- for w in wechat_wins:
- if hasattr(w, '_hWnd') and w._hWnd == fg_hwnd:
- return True
- except Exception:
- pass
- return False
-
# ── main loop (every 5 seconds) ──
def _main_loop_tick(self):
if not self.running:
# ② 找可见的"微信"窗口
wechat_windows = _find_wechat_windows()
visible = [w for w in wechat_windows if w.visible]
- if not visible:
+ # 排除最小化窗口(最小化到任务栏也算"visible"但实际不可交互)
+ active = [w for w in visible if not win32gui.IsIconic(w._hWnd)]
+ if not active:
self._set_status("微信运行中")
return
+ # 改用 active 进行后续判断
+ visible = active
# ③ 窗口尺寸判断(零API)
login_window = None
if not login_window:
self._set_status("微信运行中")
if visible:
- log.info("微信已登录(主界面 %dx%d)", visible[0].width, visible[0].height)
+ self._log_state("info", "微信已登录(主界面)")
else:
- log.info("微信已登录(主界面,无可见窗口)")
+ self._log_state("info", "微信已登录(主界面)")
return
# ④ 最小化其他窗口
- # 微信在前端就不最小化,避免打断用户
+ # 微信在登录窗口且在前端时,跳过最小化
if not self._is_wechat_foreground():
_minimize_all_except_wechat()
time.sleep(0.3)
if not login_window:
# 窗口变大了 → 登录成功
self._set_status("微信运行中")
- log.info("微信已登录(窗口变大)")
+ self._log_state("info", "微信已登录(主界面)")
if self.hash_mode:
self.hash_mode = False
self._last_login_hash = None
elif result == "B":
self.qr_sent_count += 1
self._set_status(f"请扫码登录 ({self.qr_sent_count}/{MAX_EMAILS})")
- log.info("检测到二维码,第 %d 次通知", self.qr_sent_count)
+ self._log_state("info", "检测到二维码")
qr_path = os.path.join(tempfile.gettempdir(), f"wechat_qr_{int(time.time())}.png")
img.save(qr_path, "PNG")
send_qr_email(qr_path)
# ③ 查窗口尺寸
wechat_windows = _find_wechat_windows()
visible = [w for w in wechat_windows if w.visible]
+ # 排除最小化窗口(最小化到任务栏也算"visible"但实际不可交互)
+ active = [w for w in visible if not win32gui.IsIconic(w._hWnd)]
+ if not active:
+ self._set_status("微信运行中")
+ return
+ # 改用 active 进行后续判断
+ visible = active
login_window = None
for w in visible:
if w.width < 700 and w.height < 850:
self._last_login_hash = None
self.qr_sent_count = 0
self._set_status("微信运行中")
- log.info("微信已登录(主界面),退出哈希监测")
+ self._log_state("info", "微信已登录(主界面)")
return
# ④ 截图+哈希比较
- # 微信在前端就不最小化
+ # 微信在登录窗口且在前端时,跳过最小化
if not self._is_wechat_foreground():
_minimize_all_except_wechat()
time.sleep(0.3)
+ else:
+ time.sleep(0.3)
img = _capture_center()
new_md5 = _md5_of_image(img)
return
# 哈希变了:检查窗口尺寸是否变化
- log.info("二维码已变化,检查登录状态...")
+ self._log_state("info", "二维码已变化")
wechat_windows = _find_wechat_windows()
visible = [w for w in wechat_windows if w.visible]
still_login = False
self._last_login_hash = None
self.qr_sent_count = 0
self._set_status("微信运行中")
- log.info("微信已登录,退出哈希监测")
+ self._log_state("info", "微信已登录(主界面)")
return
# 仍然是登录窗口→发通知
self.qr_sent_count = 0
self._resend_link_sent = False
self._set_status("微信运行中")
- log.info("微信已登录,退出等待重发模式")
+ self._log_state("info", "微信已登录(主界面)")
return
# ② 查flag