先声明:代码由本人编写,但是由于本人代码编写不太规范,为了方便理解,所以让AI添加注释并且修改函数名

介绍
超级老板键:可以隐藏窗口,一键恢复多个窗口,可以隐藏自身。如图,可以点左下角添加配置,可以添加多个老板键隐藏多个窗口。点击右边“捕获”可以自定义老板键,配置会保存在当前目录下。隐藏有三个选项,可以自己选择:隐藏老板键自身,隐藏最表层窗口和隐藏指定窗口(要写窗口标题)。配置好后点击”启动老板键“即可开始使用,有一键恢复窗口。
备注:因为我设置了无控制台(就是没有黑窗),所以360不知道为啥就报毒,各位不放心可以看看源码,或者自己反编译,spec也在附件中!,。以下内容便于检查人员反编译:python的打包版本:"""E:\练手项目\项目3老板键>python --version
Python 3.10.8
pyinstaller版本E:\练手项目\项目3老板键>pyinstaller -v
6.14.2"""
问题修复等内容
如果遇到问题或者bug可以打开老板键所在目录,底下会有log.txt文件,将文件和你的问题或bug发给我,我看到会处理。如果有其他想要的功能也可以私信我哦!
源代码:
import os
import sys
# ---------- 隐藏控制台黑窗(仅 Windows)----------
if sys.platform == "win32":
import ctypes
ctypes.windll.kernel32.FreeConsole()
import tkinter as tk
from tkinter import ttk, messagebox
import threading
import queue
import json
import logging
# ---------- 依赖库 ----------
import keyboard
import pygetwindow as gw
import win32gui
import win32con
import win32event
import win32api
import winerror
# ---------- 日志配置(追加模式)----------
LOG_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "log.txt")
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(LOG_FILE, mode='a', encoding='utf-8')
]
)
logger = logging.getLogger(__name__)
CONFIG_FILE = "bosskey_config.json"
# ---------- 进程互斥,防止多开 ----------
MUTEX_NAME = "Global\\BossKeyAppMutex"
mutex = win32event.CreateMutex(None, False, MUTEX_NAME)
if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS:
logger.warning("检测到已有实例运行,退出")
sys.exit(0)
# ---------------------- 单个隐藏配置项的数据模型 ----------------------
class HideConfigItem:
"""
一个隐藏规则:包含启用状态、类型、快捷键、目标标题,以及运行时隐藏的窗口句柄
"""
# 内部英文标识
HIDE_SELF = "self" # 隐藏自身窗口
HIDE_TOPMOST = "topmost" # 隐藏最表层窗口
HIDE_TARGET = "target" # 隐藏指定标题窗口
# ★ 中文显示映射
TYPE_MAP = {
HIDE_SELF: "隐藏自身",
HIDE_TOPMOST: "隐藏最表层窗口",
HIDE_TARGET: "隐藏指定窗口"
}
REVERSE_MAP = {v: k for k, v in TYPE_MAP.items()}
def __init__(self, enable=True, hide_type=HIDE_TOPMOST, hotkey="", target_title=""):
self.enable = tk.BooleanVar(value=enable)
self.hide_type = tk.StringVar(value=hide_type) # 内部英文
self.hotkey = tk.StringVar(value=hotkey)
self.target_title = tk.StringVar(value=target_title)
# ★ 用于界面显示的中文变量,与 hide_type 自动同步
self.type_display = tk.StringVar(value=self.TYPE_MAP.get(hide_type, "隐藏最表层窗口"))
# 当 type_display 变化时,更新 hide_type
self.type_display.trace("w", self._sync_hide_type)
# 运行时状态
self.hidden_hwnds = []
self.hidden_self = False
def _sync_hide_type(self, *args):
"""将中文显示值转换为英文内部值"""
eng = self.REVERSE_MAP.get(self.type_display.get(), self.HIDE_TOPMOST)
if self.hide_type.get() != eng:
self.hide_type.set(eng)
def get_hidden_any(self):
if self.hide_type.get() == self.HIDE_SELF:
return self.hidden_self
elif self.hide_type.get() == self.HIDE_TOPMOST:
return len(self.hidden_hwnds) > 0 and win32gui.IsWindow(self.hidden_hwnds[0])
else:
return any(win32gui.IsWindow(hwnd) for hwnd in self.hidden_hwnds)
def to_dict(self):
return {
"enable": self.enable.get(),
"type": self.hide_type.get(), # 保存英文标识
"hotkey": self.hotkey.get(),
"target_title": self.target_title.get()
}
@classmethod
def from_dict(cls, data):
item = cls(
enable=data.get("enable", True),
hide_type=data.get("type", cls.HIDE_TOPMOST),
hotkey=data.get("hotkey", ""),
target_title=data.get("target_title", "")
)
# 保证显示与内部值一致
item.type_display.set(cls.TYPE_MAP.get(item.hide_type.get(), "隐藏最表层窗口"))
return item
class BossKeyApp:
def __init__(self, root, auto_start=False):
self.root = root
self.root.title("老板键 v3.0 - 多配置版")
self.root.geometry("620x550")
self.root.resizable(True, True)
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
self.auto_start = auto_start
# ---------- 动态配置列表 ----------
self.config_items = []
self.config_frames = []
# ---------- 状态 ----------
self.active = False
self.action_queue = queue.Queue()
self.registered_hotkeys = set()
self.self_hidden = False
self.load_config()
self.build_ui()
if self.auto_start:
self.root.after(500, self.auto_elevated_start)
self.process_queue()
logger.info("程序启动")
# ---------------------- 界面构建 ----------------------
def build_ui(self):
ttk.Label(self.root, text="老板键设置(可添加多条规则)", font=("微软雅黑", 12, "bold")).pack(pady=(10, 5))
# ---------- 可滚动的配置列表区域 ----------
container = ttk.Frame(self.root)
container.pack(fill="both", expand=True, padx=20, pady=4)
canvas = tk.Canvas(container, borderwidth=0, highlightthickness=0)
scrollbar = ttk.Scrollbar(container, orient="vertical", command=canvas.yview)
self.config_list_frame = ttk.Frame(canvas)
self.config_list_frame.bind("<Configure>",
lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
canvas.create_window((0, 0), window=self.config_list_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
def _on_mousewheel(event):
canvas.yview_scroll(int(-1*(event.delta/120)), "units")
canvas.bind_all("<MouseWheel>", _on_mousewheel)
for item in self.config_items:
self._add_config_row(item)
if not self.config_items:
default_item = HideConfigItem(hide_type=HideConfigItem.HIDE_TOPMOST, hotkey="ctrl+shift+f10")
self.config_items.append(default_item)
self._add_config_row(default_item)
# ---------- 按钮区 ----------
bottom_frame = ttk.Frame(self.root)
bottom_frame.pack(pady=(8, 5), fill="x", padx=20)
btn_add = ttk.Button(bottom_frame, text="添加配置项", command=self.add_config_item)
btn_add.pack(side="left", padx=5)
self.start_btn = ttk.Button(bottom_frame, text="启动老板键", command=self.start)
self.start_btn.pack(side="left", padx=5)
self.stop_btn = ttk.Button(bottom_frame, text="停止老板键", command=self.stop, state="disabled")
self.stop_btn.pack(side="left", padx=5)
self.recover_all_btn = ttk.Button(bottom_frame, text="一键恢复所有隐藏窗口", command=self.recover_all_windows)
self.recover_all_btn.pack(side="left", padx=5)
self.status_label = ttk.Label(self.root, text="状态:未启动", foreground="gray")
self.status_label.pack(pady=(2, 10))
def _add_config_row(self, item):
frame = ttk.Frame(self.config_list_frame)
frame.pack(fill="x", pady=3, padx=2)
# 启用复选框
cb = ttk.Checkbutton(frame, variable=item.enable)
cb.pack(side="left", padx=(5, 2))
# ★ 类型下拉(显示中文)
type_combo = ttk.Combobox(frame, textvariable=item.type_display,
values=["隐藏自身", "隐藏最表层窗口", "隐藏指定窗口"],
state="readonly", width=14)
type_combo.pack(side="left", padx=2)
# 快捷键输入框
hotkey_entry = ttk.Entry(frame, textvariable=item.hotkey, width=18, font=("Consolas", 10))
hotkey_entry.pack(side="left", padx=2)
# 捕获按钮
btn_capture = ttk.Button(frame, text="捕获",
command=lambda it=item: self.capture_hotkey(it.hotkey))
btn_capture.pack(side="left", padx=2)
# 目标标题输入(仅当类型为 target 时显示)
title_entry = ttk.Entry(frame, textvariable=item.target_title, width=20)
title_label = ttk.Label(frame, text="标题:")
def update_title_visibility(*args):
if item.hide_type.get() == HideConfigItem.HIDE_TARGET:
title_label.pack(side="left", padx=(10, 2))
title_entry.pack(side="left", padx=2)
else:
title_label.pack_forget()
title_entry.pack_forget()
item.hide_type.trace("w", update_title_visibility)
update_title_visibility()
# 删除按钮
btn_del = ttk.Button(frame, text="删除",
command=lambda f=frame, it=item: self.delete_config_item(f, it))
btn_del.pack(side="right", padx=5)
self.config_frames.append(frame)
def add_config_item(self):
new_item = HideConfigItem(hide_type=HideConfigItem.HIDE_TOPMOST, hotkey="")
self.config_items.append(new_item)
self._add_config_row(new_item)
def delete_config_item(self, frame, item):
if len(self.config_items) <= 1:
messagebox.showinfo("提示", "至少保留一个配置项")
return
if self.active:
messagebox.showwarning("提示", "请先停止老板键再删除配置")
return
self.config_items.remove(item)
frame.destroy()
self.config_frames.remove(frame)
# ---------------------- 一键恢复所有隐藏窗口 ----------------------
def recover_all_windows(self):
recovered = 0
if self.root.state() == "withdrawn":
self.root.deiconify()
self.root.lift()
self.root.focus_force()
recovered += 1
logger.info("一键恢复:自身窗口已显示")
for item in self.config_items:
if item.hide_type.get() == HideConfigItem.HIDE_SELF:
if self.root.state() == "withdrawn":
pass
else:
for hwnd in item.hidden_hwnds:
if win32gui.IsWindow(hwnd):
win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
recovered += 1
item.hidden_hwnds.clear()
if item.hide_type.get() == HideConfigItem.HIDE_SELF:
item.hidden_self = False
self.action_queue.put(("status", f"一键恢复完成,共恢复 {recovered} 个窗口"))
# ---------------------- 权限工具 ----------------------
@staticmethod
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
@staticmethod
def run_as_admin():
try:
if getattr(sys, 'frozen', False):
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, '--elevated', None, 1)
else:
script = sys.argv[0]
params = f'"{script}" --elevated'
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, params, None, 1)
except Exception as e:
logger.error(f"请求管理员权限失败: {e}")
def auto_elevated_start(self):
logger.info("以管理员权限静默启动老板键")
self.start()
if self.active:
self.root.withdraw()
logger.info("窗口已隐藏,后台监听热键")
# ---------------------- 每个配置项的切换逻辑 ----------------------
def toggle_by_item(self, item):
t = item.hide_type.get()
if t == HideConfigItem.HIDE_SELF:
self._toggle_self(item)
elif t == HideConfigItem.HIDE_TOPMOST:
self._toggle_topmost(item)
elif t == HideConfigItem.HIDE_TARGET:
self._toggle_target(item)
def _toggle_self(self, item):
if self.root.state() == "withdrawn":
self.root.deiconify()
self.root.lift()
self.root.focus_force()
item.hidden_self = False
self.action_queue.put(("status", "自身窗口已显示"))
logger.info("自身窗口已显示")
else:
self.root.withdraw()
item.hidden_self = True
self.action_queue.put(("status", "自身窗口已隐藏"))
logger.info("自身窗口已隐藏")
def _toggle_topmost(self, item):
if item.hidden_hwnds and win32gui.IsWindow(item.hidden_hwnds[0]):
hwnd = item.hidden_hwnds[0]
win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
title = win32gui.GetWindowText(hwnd)
item.hidden_hwnds.clear()
self.action_queue.put(("status", f"已恢复窗口:{title}"))
logger.info(f"恢复最表层窗口:{title}")
else:
hwnd = win32gui.GetForegroundWindow()
if hwnd:
title = win32gui.GetWindowText(hwnd)
if hwnd == self.root.winfo_id():
self.action_queue.put(("status", "不能隐藏自身窗口,请使用自身隐藏规则"))
return
win32gui.ShowWindow(hwnd, win32con.SW_HIDE)
item.hidden_hwnds = [hwnd]
self.action_queue.put(("status", f"已隐藏窗口:{title}"))
logger.info(f"隐藏最表层窗口:{title}")
else:
self.action_queue.put(("status", "未找到前台窗口"))
def _toggle_target(self, item):
if item.hidden_hwnds:
restored = 0
for hwnd in item.hidden_hwnds:
if win32gui.IsWindow(hwnd):
win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
restored += 1
item.hidden_hwnds.clear()
self.action_queue.put(("status", f"已显示 {restored} 个窗口"))
logger.info(f"目标窗口已恢复,数量: {restored}")
else:
title = item.target_title.get().strip()
if not title:
self.action_queue.put(("status", "请填写目标窗口标题关键字!"))
logger.warning("目标隐藏:标题为空")
return
matches = gw.getWindowsWithTitle(title)
if not matches:
self.action_queue.put(("status", f"未找到包含 '{title}' 的窗口"))
logger.info(f"未找到匹配窗口: {title}")
return
hidden = 0
for win in matches:
if win.visible:
win.hide()
item.hidden_hwnds.append(win._hWnd)
hidden += 1
if hidden:
self.action_queue.put(("status", f"已隐藏 {hidden} 个窗口"))
logger.info(f"隐藏目标窗口: {title},数量: {hidden}")
else:
self.action_queue.put(("status", "没有可见的匹配窗口需要隐藏"))
logger.info(f"没有可见的匹配窗口: {title}")
# ---------------------- 热键注册(基于配置列表)---------------------
def _start_hotkeys(self):
try:
registered = set()
for item in self.config_items:
if not item.enable.get():
continue
hk = item.hotkey.get().strip()
if not hk:
continue
try:
keyboard.remove_hotkey(hk)
except:
pass
keyboard.add_hotkey(hk, lambda it=item: self.action_queue.put(("toggle_item", it)))
registered.add(hk)
logger.info(f"注册热键: {hk} (类型: {item.hide_type.get()})")
self.registered_hotkeys = registered
return True
except Exception as e:
logger.error(f"注册热键失败: {e}")
return False
def _stop_hotkeys(self):
for hk in self.registered_hotkeys:
try:
keyboard.remove_hotkey(hk)
except:
pass
self.registered_hotkeys.clear()
for item in self.config_items:
for hwnd in item.hidden_hwnds:
if win32gui.IsWindow(hwnd):
win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
item.hidden_hwnds.clear()
if item.hide_type.get() == HideConfigItem.HIDE_SELF:
item.hidden_self = False
if self.root.state() == "withdrawn":
self.root.deiconify()
self.active = False
self.start_btn.config(state="normal")
self.stop_btn.config(state="disabled")
self.status_label.config(text="状态:已停止")
logger.info("老板键已停止")
def start(self):
if self.active:
messagebox.showinfo("提示", "老板键已启动,无需重复操作")
return
valid = False
for item in self.config_items:
if item.enable.get() and item.hotkey.get().strip():
valid = True
break
if not valid:
messagebox.showwarning("提示", "请至少启用一个配置项并设置快捷键!")
return
if not self.is_admin():
if not messagebox.askyesno("权限提示",
"注册全局热键通常需要管理员权限,否则可能无效。\n是否继续尝试启动?"):
return
if self._start_hotkeys():
self.active = True
self.start_btn.config(state="disabled")
self.stop_btn.config(state="normal")
self.status_label.config(text="状态:已启动(老板键生效)")
self.save_config()
logger.info("老板键已启动")
else:
if not self.is_admin():
if messagebox.askyesno("需要管理员权限",
"注册全局热键失败。是否以管理员身份重新启动程序?"):
self.save_config()
self.run_as_admin()
self.root.destroy()
sys.exit(0)
else:
messagebox.showinfo("取消", "老板键未启动。")
else:
messagebox.showerror("错误", "热键注册失败,请检查快捷键是否被占用。")
def stop(self):
self.action_queue.put(("stop",))
self.status_label.config(text="状态:已停止")
def on_closing(self):
if self.active:
self._stop_hotkeys()
logger.info("程序退出")
self.root.destroy()
# ---------------------- 快捷键捕获与队列 ----------------------
def capture_hotkey(self, var):
def _capture():
try:
self.action_queue.put(("status", "请按下组合键..."))
hotkey_str = keyboard.read_hotkey(suppress=False)
self.action_queue.put(("update_hotkey", var, hotkey_str))
logger.info(f"捕获快捷键: {hotkey_str}")
except Exception as e:
self.action_queue.put(("status", f"捕获失败: {e}"))
logger.error(f"捕获快捷键失败: {e}")
threading.Thread(target=_capture, daemon=True).start()
def process_queue(self):
try:
while True:
cmd = self.action_queue.get_nowait()
if cmd[0] == "status":
self.status_label.config(text=cmd[1])
elif cmd[0] == "update_hotkey":
_, var, value = cmd
var.set(value)
elif cmd[0] == "toggle_item":
item = cmd[1]
self.toggle_by_item(item)
elif cmd[0] == "stop":
self._stop_hotkeys()
except queue.Empty:
pass
self.root.after(100, self.process_queue)
# ---------------------- 配置持久化 ----------------------
def save_config(self):
data = [item.to_dict() for item in self.config_items]
try:
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
logger.debug("配置已保存")
except Exception as e:
logger.error(f"保存配置失败: {e}")
def load_config(self):
if os.path.exists(CONFIG_FILE):
try:
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
data = json.load(f)
if isinstance(data, list):
for item_data in data:
self.config_items.append(HideConfigItem.from_dict(item_data))
else:
# 兼容旧版单个配置
logger.info("检测到旧版配置,正在转换...")
old = data
if old.get("enable_self"):
self.config_items.append(HideConfigItem(
enable=True, hide_type=HideConfigItem.HIDE_SELF,
hotkey=old.get("self_hotkey", "ctrl+shift+f9")
))
if old.get("enable_topmost"):
self.config_items.append(HideConfigItem(
enable=True, hide_type=HideConfigItem.HIDE_TOPMOST,
hotkey=old.get("topmost_hotkey", "ctrl+shift+f11")
))
if old.get("enable_target"):
self.config_items.append(HideConfigItem(
enable=True, hide_type=HideConfigItem.HIDE_TARGET,
hotkey=old.get("target_hotkey", "ctrl+shift+f10"),
target_title=old.get("target_title", "")
))
logger.info("已加载历史配置")
except Exception as e:
logger.error(f"加载配置失败: {e}")
# ---------------------- 主入口 ----------------------
if __name__ == "__main__":
auto_mode = "--elevated" in sys.argv
root = tk.Tk()
app = BossKeyApp(root, auto_start=auto_mode)
root.mainloop()







