diff --git a/.gitignore b/.gitignore index 315d011..4014716 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ config.json user.ini *.lock out/ -test.py \ No newline at end of file +test.py +pssuspend64.exe \ No newline at end of file diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..27890c4 Binary files /dev/null and b/logo.png differ diff --git a/main/Boss-Key.py b/main/Boss-Key.py index 068ea54..7a5e3e0 100644 --- a/main/Boss-Key.py +++ b/main/Boss-Key.py @@ -31,10 +31,19 @@ class APP(wx.App): def __init__(self): wx.App.__init__(self) def clean(): + print("Global Cleaning up...") + try: + Config.HotkeyListener._cleanup() + except: + pass try: Config.HotkeyListener.Close() except: pass + try: + os.remove(os.path.join(Config.root_path,"Boss-Key.lock")) + except: + pass atexit.register(clean) # 设置语言环境为中文 diff --git a/main/GUI/setting/base.py b/main/GUI/setting/base.py index 6a630a4..c76fbab 100644 --- a/main/GUI/setting/base.py +++ b/main/GUI/setting/base.py @@ -36,8 +36,8 @@ def init_UI(self): # 创建按钮 button_sizer = wx.BoxSizer(wx.HORIZONTAL) - self.reset_btn = wx.Button(panel, label="重置设置") - self.save_btn = wx.Button(panel, label="保存设置") + self.reset_btn = wx.Button(panel, label="重置设置", size=(-1, 50)) + self.save_btn = wx.Button(panel, label="保存设置", size=(-1, 50)) button_sizer.Add(self.reset_btn, proportion=1, flag=wx.LEFT, border=20) button_sizer.Add(self.save_btn, proportion=1, flag=wx.RIGHT, border=20) diff --git a/main/GUI/setting/hotkeys_page.py b/main/GUI/setting/hotkeys_page.py index a7e2998..b37c58b 100644 --- a/main/GUI/setting/hotkeys_page.py +++ b/main/GUI/setting/hotkeys_page.py @@ -11,7 +11,10 @@ def __init__(self, parent): def init_UI(self): sizer = wx.BoxSizer(wx.VERTICAL) - # 创建网格布局 + # 创建键盘热键设置区域 + keyboard_box = wx.StaticBox(self, label="键盘热键") + keyboard_box_sizer = wx.StaticBoxSizer(keyboard_box, wx.VERTICAL) + grid_sizer = wx.FlexGridSizer(rows=2, cols=3, gap=(10, 20)) grid_sizer.AddGrowableCol(1, 1) @@ -33,25 +36,105 @@ def init_UI(self): grid_sizer.Add(self.close_text, 1, wx.EXPAND | wx.ALL, 10) grid_sizer.Add(self.close_btn, 0, wx.EXPAND | wx.ALL, 10) - sizer.Add(grid_sizer, 0, wx.EXPAND | wx.ALL, 10) + keyboard_box_sizer.Add(grid_sizer, 0, wx.EXPAND | wx.ALL, 5) + sizer.Add(keyboard_box_sizer, 0, wx.EXPAND | wx.ALL, 10) + + # 添加鼠标隐藏选项 + mouse_box = wx.StaticBox(self, label="鼠标隐藏") + mouse_box_sizer = wx.StaticBoxSizer(mouse_box, wx.VERTICAL) + + # 中键选项 + self.middle_button_checkbox = wx.CheckBox(self, label="启用鼠标中键隐藏窗口") + self.middle_button_checkbox.SetToolTip(wx.ToolTip("点击鼠标中键可快速隐藏/显示窗口")) + + # 侧键1选项 + self.side_button1_checkbox = wx.CheckBox(self, label="启用鼠标侧键1隐藏窗口") + self.side_button1_checkbox.SetToolTip(wx.ToolTip("点击鼠标侧键1(前进键)可快速隐藏/显示窗口")) + + # 侧键2选项 + self.side_button2_checkbox = wx.CheckBox(self, label="启用鼠标侧键2隐藏窗口") + self.side_button2_checkbox.SetToolTip(wx.ToolTip("点击鼠标侧键2(后退键)可快速隐藏/显示窗口")) + + mouse_box_sizer.Add(self.middle_button_checkbox, 0, wx.ALL, 10) + mouse_box_sizer.Add(self.side_button1_checkbox, 0, wx.ALL, 10) + mouse_box_sizer.Add(self.side_button2_checkbox, 0, wx.ALL, 10) + + sizer.Add(mouse_box_sizer, 0, wx.EXPAND | wx.ALL, 10) + + # 添加其他选项区域 + other_box = wx.StaticBox(self, label="其他") + other_box_sizer = wx.StaticBoxSizer(other_box, wx.VERTICAL) + + # 自动隐藏选项 + auto_hide_sizer = wx.BoxSizer(wx.HORIZONTAL) + self.auto_hide_checkbox = wx.CheckBox(self, label="自动隐藏:") + self.auto_hide_checkbox.SetToolTip(wx.ToolTip("在无操作指定时间后自动隐藏窗口")) + auto_hide_sizer.Add(self.auto_hide_checkbox, 0, wx.ALIGN_CENTER_VERTICAL) + + # 自动隐藏时间输入框 + self.auto_hide_time = wx.SpinCtrl(self, min=1, max=120, initial=5) + self.auto_hide_time.SetToolTip(wx.ToolTip("设置多少分钟无操作后自动隐藏")) + auto_hide_sizer.Add(self.auto_hide_time, 0, wx.LEFT, 10) + + # 分钟标签 + minutes_label = wx.StaticText(self, label="分钟") + auto_hide_sizer.Add(minutes_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5) + + other_box_sizer.Add(auto_hide_sizer, 0, wx.ALL, 10) + + # 灰色文本提示 + auto_hide_tip = wx.StaticText(self, label="当键盘和鼠标在指定时间内无操作时,将自动隐藏窗口") + auto_hide_tip.SetForegroundColour(wx.Colour(128, 128, 128)) # 灰色文本 + other_box_sizer.Add(auto_hide_tip, 0, wx.ALL, 10) + + sizer.Add(other_box_sizer, 0, wx.EXPAND | wx.ALL, 10) self.SetSizer(sizer) def Bind_EVT(self): self.hide_show_btn.Bind(wx.EVT_BUTTON, self.OnRecordHideShow) self.close_btn.Bind(wx.EVT_BUTTON, self.OnRecordClose) + self.auto_hide_checkbox.Bind(wx.EVT_CHECKBOX, self.OnAutoHideToggle) + + def OnAutoHideToggle(self, e): + # 启用或禁用时间输入框 + self.auto_hide_time.Enable(self.auto_hide_checkbox.GetValue()) def SetData(self): self.hide_show_text.SetValue(Config.hide_hotkey) self.close_text.SetValue(Config.close_hotkey) + self.middle_button_checkbox.SetValue(Config.middle_button_hide if hasattr(Config, 'middle_button_hide') else False) + self.side_button1_checkbox.SetValue(Config.side_button1_hide if hasattr(Config, 'side_button1_hide') else False) + self.side_button2_checkbox.SetValue(Config.side_button2_hide if hasattr(Config, 'side_button2_hide') else False) + + # 设置自动隐藏选项 + auto_hide_enabled = Config.auto_hide_enabled if hasattr(Config, 'auto_hide_enabled') else False + self.auto_hide_checkbox.SetValue(auto_hide_enabled) + + auto_hide_time = Config.auto_hide_time if hasattr(Config, 'auto_hide_time') else 5 + self.auto_hide_time.SetValue(auto_hide_time) + self.auto_hide_time.Enable(auto_hide_enabled) def SaveData(self): Config.hide_hotkey = self.hide_show_text.GetValue() Config.close_hotkey = self.close_text.GetValue() + Config.middle_button_hide = self.middle_button_checkbox.GetValue() + Config.side_button1_hide = self.side_button1_checkbox.GetValue() + Config.side_button2_hide = self.side_button2_checkbox.GetValue() + + # 保存自动隐藏设置 + Config.auto_hide_enabled = self.auto_hide_checkbox.GetValue() + Config.auto_hide_time = self.auto_hide_time.GetValue() def Reset(self): self.hide_show_text.SetValue("Ctrl+Q") self.close_text.SetValue("Win+Esc") + self.middle_button_checkbox.SetValue(False) + self.side_button1_checkbox.SetValue(False) + self.side_button2_checkbox.SetValue(False) + self.auto_hide_checkbox.SetValue(False) + self.auto_hide_time.SetValue(5) + self.auto_hide_time.Enable(False) def OnRecordHideShow(self, e): self.recordHotkey(self.hide_show_text, self.hide_show_btn) diff --git a/main/GUI/setting/options_page.py b/main/GUI/setting/options_page.py index 72ce557..a0fc3d4 100644 --- a/main/GUI/setting/options_page.py +++ b/main/GUI/setting/options_page.py @@ -226,7 +226,7 @@ def OnRequestAdmin(self, e=None): """请求管理员权限并重启程序""" wx.MessageBox("程序将重启并请求管理员权限", "提示", wx.OK | wx.ICON_INFORMATION) run_as_admin() - wx.GetApp().GetTopWindow().Close() + wx.GetApp().ExitMainLoop() def OnRedetectPssuspend(self, e=None): """重新检测pssuspend64.exe是否存在""" diff --git a/main/GUI/window_restore.py b/main/GUI/window_restore.py index b7c4008..16c9dad 100644 --- a/main/GUI/window_restore.py +++ b/main/GUI/window_restore.py @@ -2,7 +2,9 @@ import wx.dataview as dataview import win32gui import win32con +import win32process import webbrowser +import psutil from core import tools as tool from core.model import WindowInfo from core.config import Config @@ -84,11 +86,26 @@ def SetData(self): self.Layout() def RefreshLeftList(self, e=None): - windows = tool.getAllWindows() - list = [] - for window in windows: - list.append(window) - self.InsertTreeList(list, self.left_treelist, True) + def enumHandler(hwnd, windows): + title = tool.hwnd2windowName(hwnd) + + pid = win32process.GetWindowThreadProcessId(hwnd)[1] + process_name = psutil.Process(pid).name() + process_path = psutil.Process(pid).exe() + + windows.append(WindowInfo( + title=title, + hwnd=int(hwnd), + process=process_name, + PID=int(pid), + path=process_path + )) + return True + + windows = [] + win32gui.EnumWindows(enumHandler, windows) + windows.sort(key=lambda x: x.title) + self.InsertTreeList(windows, self.left_treelist, True) def on_refresh_window(self, e=None): """刷新窗口列表""" diff --git a/main/core/config.py b/main/core/config.py index dcf73ff..418c851 100644 --- a/main/core/config.py +++ b/main/core/config.py @@ -53,6 +53,11 @@ class Config: click_to_hide = True hide_icon_after_hide = False path_match = True + middle_button_hide = False # 新增:鼠标中键隐藏功能开关 + side_button1_hide = False # 鼠标侧键1隐藏功能开关 + side_button2_hide = False # 鼠标侧键2隐藏功能开关 + auto_hide_enabled = False # 自动隐藏功能开关 + auto_hide_time = 5 # 自动隐藏等待时间(分钟) hide_binding = [] @@ -97,6 +102,11 @@ def load(): Config.path_match = config.get("setting", {}).get("path_match", False) Config.freeze_after_hide = config.get("setting", {}).get("freeze_after_hide", False) # 加载新配置项 Config.enhanced_freeze = config.get("setting", {}).get("enhanced_freeze", False) # 加载新配置项 + Config.middle_button_hide = config.get("setting", {}).get("middle_button_hide", False) # 加载鼠标中键隐藏设置 + Config.side_button1_hide = config.get("setting", {}).get("side_button1_hide", False) # 加载鼠标侧键1隐藏设置 + Config.side_button2_hide = config.get("setting", {}).get("side_button2_hide", False) # 加载鼠标侧键2隐藏设置 + Config.auto_hide_enabled = config.get("setting", {}).get("auto_hide_enabled", False) # 加载自动隐藏功能开关 + Config.auto_hide_time = config.get("setting", {}).get("auto_hide_time", 5) # 加载自动隐藏等待时间 Config.click_to_hide= config.get("setting", {}).get("click_to_hide", True) @@ -128,7 +138,12 @@ def save(): 'hide_icon_after_hide': Config.hide_icon_after_hide, 'path_match': Config.path_match, 'freeze_after_hide': Config.freeze_after_hide, # 保存新配置项 - 'enhanced_freeze': Config.enhanced_freeze # 保存新配置项 + 'enhanced_freeze': Config.enhanced_freeze, # 保存新配置项 + 'middle_button_hide': Config.middle_button_hide, # 保存鼠标中键隐藏设置 + 'side_button1_hide': Config.side_button1_hide, # 保存鼠标侧键1隐藏设置 + 'side_button2_hide': Config.side_button2_hide, # 保存鼠标侧键2隐藏设置 + 'auto_hide_enabled': Config.auto_hide_enabled, # 保存自动隐藏功能开关 + 'auto_hide_time': Config.auto_hide_time # 保存自动隐藏等待时间 }, # 将WindowInfo对象列表转换为字典列表用于JSON序列化 "hide_binding": [item.to_dict() if isinstance(item, WindowInfo) else item for item in Config.hide_binding] diff --git a/main/core/listener.py b/main/core/listener.py index 0358aa3..f7f58cb 100644 --- a/main/core/listener.py +++ b/main/core/listener.py @@ -4,7 +4,7 @@ from win32con import SW_HIDE, SW_SHOW import win32process import sys -from pynput import keyboard +from pynput import keyboard, mouse # 确保导入mouse模块 import multiprocessing import threading import time @@ -13,16 +13,29 @@ class HotkeyListener(): def __init__(self): + # 先定义所有属性 + self.Queue = multiprocessing.Queue() + self.listener = None + self.mouse_listener = None + self.keyboard_activity_listener = None + self.mouse_activity_listener = None + self.last_activity_time = time.time() + self.auto_hide_timer = None + self.shared_state_file = os.path.join(Config.root_path, ".bosskey_state") + self.end_flag = False + + # 然后再执行可能使用这些属性的方法 try: self.ShowWindows() except: pass tool.sendNotify("Boss Key正在运行!", "Boss Key正在为您服务,您可通过托盘图标看到我") - self.Queue = multiprocessing.Queue() - self.listener = None + self.reBind() - self.end_flag=False - threading.Thread(target=self.listenToQueue,daemon=True).start() + threading.Thread(target=self.listenToQueue, daemon=True).start() + + # 启动自动隐藏监控(如果启用) + self.start_auto_hide_monitor() def listenToQueue(self): exit_flag = False @@ -40,9 +53,6 @@ def listenToQueue(self): self._stop() try: wx.GetApp().ExitMainLoop() - # wx.FindWindowById(Config.SettingWindowId).Destroy() - # wx.FindWindowById(Config.UpdateWindowId).Destroy() - # Config.TaskBarIcon.Destroy() except Exception as e: print(e) pass @@ -57,8 +67,113 @@ def listenToQueue(self): def reBind(self): self._stop() self.BindHotKey() - - def ListenerProcess(self,hotkey): + # 如果启用了任何鼠标按键隐藏,则添加鼠标监听 + if (hasattr(Config, 'middle_button_hide') and Config.middle_button_hide) or \ + (hasattr(Config, 'side_button1_hide') and Config.side_button1_hide) or \ + (hasattr(Config, 'side_button2_hide') and Config.side_button2_hide): + self.start_mouse_listener() + + # 启动自动隐藏监控(如果启用) + self.start_auto_hide_monitor() + + def start_auto_hide_monitor(self): + """启动自动隐藏监控""" + # 停止之前的监控 + self.stop_auto_hide_monitor() + + # 检查是否启用了自动隐藏 + if hasattr(Config, 'auto_hide_enabled') and Config.auto_hide_enabled: + # 启动活动监听器 + self.start_activity_listeners() + + # 启动定时器,每5秒检查一次是否需要自动隐藏 + self.auto_hide_timer = threading.Timer(5, self.check_auto_hide) + self.auto_hide_timer.daemon = True + self.auto_hide_timer.start() + + def stop_auto_hide_monitor(self): + """停止自动隐藏监控""" + # 停止定时器 + if self.auto_hide_timer: + self.auto_hide_timer.cancel() + self.auto_hide_timer = None + + # 停止活动监听器 + self.stop_activity_listeners() + + def start_activity_listeners(self): + """启动键盘和鼠标活动监听器""" + # 停止之前的监听器 + self.stop_activity_listeners() + + # 启动键盘活动监听器 + self.keyboard_activity_listener = keyboard.Listener(on_press=self.on_activity) + self.keyboard_activity_listener.daemon = True + self.keyboard_activity_listener.start() + + # 启动鼠标活动监听器 + self.mouse_activity_listener = mouse.Listener( + on_move=self.on_activity, + on_click=self.on_activity, + on_scroll=self.on_activity + ) + self.mouse_activity_listener.daemon = True + self.mouse_activity_listener.start() + + def stop_activity_listeners(self): + """停止键盘和鼠标活动监听器""" + if self.keyboard_activity_listener: + self.keyboard_activity_listener.stop() + self.keyboard_activity_listener = None + + if self.mouse_activity_listener: + self.mouse_activity_listener.stop() + self.mouse_activity_listener = None + + def on_activity(self, *args, **kwargs): + """记录最后一次活动时间""" + self.last_activity_time = time.time() + + def check_auto_hide(self): + """检查是否需要自动隐藏""" + try: + # 重新加载配置 + if hasattr(Config, 'auto_hide_enabled') and Config.auto_hide_enabled: + # 计算闲置时间(秒) + idle_time = time.time() - self.last_activity_time + # 转换自动隐藏时间为秒 + auto_hide_seconds = Config.auto_hide_time * 60 + + # 如果闲置时间超过设定的自动隐藏时间,且窗口当前是显示状态 + if idle_time >= auto_hide_seconds and self.get_windows_state() == 1: + # 执行隐藏操作,修复了这里的错误调用 + wx.CallAfter(self.onHide) + + finally: + # 如果仍然启用了自动隐藏,则设置下一次检查 + if hasattr(Config, 'auto_hide_enabled') and Config.auto_hide_enabled: + self.auto_hide_timer = threading.Timer(5, self.check_auto_hide) + self.auto_hide_timer.daemon = True + self.auto_hide_timer.start() + + def start_mouse_listener(self): + """启动鼠标监听器""" + if self.mouse_listener is None or not self.mouse_listener.is_alive(): + self.mouse_listener = mouse.Listener(on_click=self.on_mouse_click) + self.mouse_listener.daemon = True + self.mouse_listener.start() + + def on_mouse_click(self, x, y, button, pressed): + """鼠标点击事件处理""" + if pressed: # 只在按下时触发,不在松开时触发 + if (button == mouse.Button.middle and Config.middle_button_hide) or \ + (button == mouse.Button.x1 and Config.side_button1_hide) or \ + (button == mouse.Button.x2 and Config.side_button2_hide): + # 在主线程中执行onHide + wx.CallAfter(self.onHide) + + def ListenerProcess(self, hotkey): + """键盘热键监听进程""" try: with keyboard.GlobalHotKeys(hotkey) as listener: self.end_flag = False @@ -71,7 +186,8 @@ def ListenerProcess(self,hotkey): print("热键监听已停止") except Exception as e: - self.ShowWindows(False) + # 热键监听出错时尝试恢复窗口 + self.set_windows_state(1) # 强制设置状态为显示 print(f"热键监听出错: {e}") def BindHotKey(self): @@ -81,18 +197,42 @@ def BindHotKey(self): } hotkeys = tool.keyConvert(hotkeys) - self.listener = multiprocessing.Process(target=self.ListenerProcess,daemon=True,args=(hotkeys,),name="Boss-Key热键监听进程") + self.listener = multiprocessing.Process(target=self.ListenerProcess, daemon=True, args=(hotkeys,), name="Boss-Key热键监听进程") self.listener.start() - def onHide(self,e=""): - if Config.times == 1: + def get_windows_state(self): + """获取窗口状态,1=显示,0=隐藏""" + try: + if os.path.exists(self.shared_state_file): + with open(self.shared_state_file, 'r') as f: + return int(f.read().strip() or '1') + return 1 # 默认状态为显示 + except: + return 1 # 出错时默认状态为显示 + + def set_windows_state(self, state): + """设置窗口状态,1=显示,0=隐藏""" + try: + with open(self.shared_state_file, 'w') as f: + f.write(str(state)) + Config.times = state # 同时更新内存中的状态 + except Exception as e: + print(f"设置窗口状态失败: {e}") + + def onHide(self, e=""): + """根据当前状态切换窗口显示/隐藏""" + # 从共享状态文件获取当前状态 + current_state = self.get_windows_state() + + if current_state == 1: # 隐藏窗口 self.HideWindows() else: + # 显示窗口 self.ShowWindows() - def ShowWindows(self,load=True): - # 显示窗口 + def ShowWindows(self, load=True): + """显示之前隐藏的窗口""" if load: Config.load() @@ -108,34 +248,34 @@ def ShowWindows(self,load=True): for i in Config.history: ShowWindow(i, SW_SHOW) if Config.mute_after_hide: - tool.changeMute(i,0) + tool.changeMute(i, 0) if Config.hide_icon_after_hide: self.Queue.put("showTaskBarIcon") - Config.times = 1 + # 更新状态 + self.set_windows_state(1) Config.save() def HideWindows(self): - # 隐藏窗口 - + """隐藏指定的窗口""" Config.load() - needHide=[] - frozen_pids=[] - windows=tool.getAllWindows() + needHide = [] + frozen_pids = [] + windows = tool.getAllWindows() - outer=windows - inner=Config.hide_binding + outer = windows + inner = Config.hide_binding - #减少循环次数,选择相对较少的做外循环 + # 减少循环次数,选择相对较少的做外循环 if len(Config.hide_binding) < len(windows): - outer=Config.hide_binding - inner=windows + outer = Config.hide_binding + inner = windows for i in outer: for j in inner: if tool.isSameWindow(i, j, False, not Config.path_match): - if outer==Config.hide_binding: # 此时i是绑定的元素,j是窗口元素,需要隐藏j + if outer == Config.hide_binding: # 此时i是绑定的元素,j是窗口元素,需要隐藏j needHide.append(j.hwnd) if Config.freeze_after_hide and hasattr(j, 'PID') and j.PID: frozen_pids.append(j.PID) @@ -145,7 +285,7 @@ def HideWindows(self): frozen_pids.append(i.PID) break - if Config.hide_current: # 插入当前窗口的句柄 + if Config.hide_current: # 插入当前窗口的句柄 hwnd = GetForegroundWindow() needHide.append(hwnd) # 如果需要冻结进程,获取当前窗口的PID @@ -153,13 +293,13 @@ def HideWindows(self): try: pid = win32process.GetWindowThreadProcessId(hwnd)[1] current_pid = win32process.GetCurrentProcessId() # 获取当前程序的PID - if pid != current_pid and pid !=os.getpid(): # 如果当前窗口的pid与本程序的pid相同,则不冻结 + if pid != current_pid and pid != os.getpid(): # 如果当前窗口的pid与本程序的pid相同,则不冻结 frozen_pids.append(pid) except: pass - needHide=tool.remove_duplicates(needHide) # 去重 - frozen_pids=tool.remove_duplicates(frozen_pids) if Config.freeze_after_hide else [] # 去重 + needHide = tool.remove_duplicates(needHide) # 去重 + frozen_pids = tool.remove_duplicates(frozen_pids) if Config.freeze_after_hide else [] # 去重 for i in needHide: if Config.send_before_hide: @@ -168,7 +308,7 @@ def HideWindows(self): ShowWindow(i, SW_HIDE) if Config.mute_after_hide: - tool.changeMute(i,1) + tool.changeMute(i, 1) # 冻结进程 if Config.freeze_after_hide and frozen_pids: @@ -179,13 +319,14 @@ def HideWindows(self): print(f"冻结进程失败: {e}") Config.frozen_pids = frozen_pids - Config.history=needHide - Config.times = 0 + Config.history = needHide + # 更新状态 + self.set_windows_state(0) if Config.hide_icon_after_hide: self.Queue.put("hideTaskBarIcon") Config.save() - def Close(self,e=""): + def Close(self, e=""): self.Queue.put("closeApp") def _stop(self): @@ -193,7 +334,7 @@ def _stop(self): 直接关闭listener,应该使用Close """ if self.listener is not None: - self.end_flag=True + self.end_flag = True try: self.listener.terminate() self.listener.join() @@ -201,3 +342,24 @@ def _stop(self): pass finally: self.listener = None + + # 停止鼠标监听器 + if hasattr(self, 'mouse_listener') and self.mouse_listener is not None: + try: + self.mouse_listener.stop() + self.mouse_listener = None + except: + pass + + # 停止自动隐藏监控 + self.stop_auto_hide_monitor() + self._cleanup() + + def _cleanup(self): + # 清理状态文件 + try: + if hasattr(self, 'shared_state_file') and os.path.exists(self.shared_state_file): + os.remove(self.shared_state_file) + print("已清理状态文件") + except Exception as e: + print(f"清理状态文件失败: {e}")