章鱼哥资源网,爱干净的章鱼哥.懒人资源吧,资源网,小刀娱乐网,小黑辅助网,资源分享,软件分享

摸鱼必备:超级老板键:可以隐藏多个窗口!

章鱼哥 酷玩资源

先声明:代码由本人编写,但是由于本人代码编写不太规范,为了方便理解,所以让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()

相关链接:

免责声明:

本站提供的资源,都来自网络,版权争议与本站无关,所有内容及软件的文章仅限用于学习和研究目的。不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负,我们不保证内容的长久可用性,通过使用本站内容随之而来的风险与本站无关,您必须在下载后的24个小时之内,从您的电脑/手机中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。侵删请致信E-mail:lrkingcn@qq.com

评论列表
提交友情链接
×

友情链接提交

请先做上本站链接,审核后会通过的

章鱼哥资源网 - https://www.lrking.cn