[Python] 纯文本查看 复制代码
import sys
import time
import threading
import subprocess
import os
import ctypes
from ctypes import wintypes
import keyboard
import win32gui
import win32process
import win32con
import tkinter as tk
from tkinter import simpledialog, messagebox
import psutil
from datetime import datetime
# ======== 配置 ========
WHITELIST = {"potplayermini64", "et"} # 白名单程序(不带扩展名)
EXEMPT_PROCESSES = {
"explorer", "runtimebroker", "searchapp", "sihost",
"taskhostw", "applicationframehost", "startmenuexperiencehost",
"systemsettings", "lockapp", "svchost", "conhost",
"cmd", "powershell", "python", "pythonw", "pycharm64", "vsdebugger"
}
# 白名单程序的自定义路径(绿色版专用)
WHITELIST_PATHS = {
"potplayermini64": r"C:\Not Delete\РotРlayer 1.7.21999 x64\PotPlayerMini64.exe",
"et": r"C:\Program Files\11.8.2.11813\office6\et.exe",
}
# ======== 日期计算配置 ========
DEFAULT_DATE = "2026-06-15" # 用于计算“已经过去了XX天”的起始日期
GRADUATION_DATE = "2026-06-30" # 毕业日期(毕业第10年)
UPDATE_INTERVAL_MS = 21600000 # 每6小时更新一次
# ======== 弹窗获取锁定时间 ========
def get_lock_duration():
temp_root = tk.Tk()
temp_root.withdraw()
minutes = simpledialog.askinteger(
"锁定时间设置",
"请输入锁定时间(分钟):\n(取消则使用默认30分钟)",
parent=temp_root,
minvalue=1,
maxvalue=1440
)
temp_root.destroy()
if minutes is None:
minutes = 30
messagebox.showinfo("提示", "使用默认锁定时间:30分钟")
return minutes * 60
LOCK_DURATION_SECONDS = get_lock_duration()
# ======== 全局状态 ========
locked = True
timer_running = False
is_white_active = False
# ======== 藏/显任务栏 ========
def hide_taskbar():
tray = win32gui.FindWindow("Shell_TrayWnd", None)
if tray:
win32gui.ShowWindow(tray, win32con.SW_HIDE)
def show_taskbar():
tray = win32gui.FindWindow("Shell_TrayWnd", None)
if tray:
win32gui.ShowWindow(tray, win32con.SW_SHOW)
# ======== 解锁函数 ========
def unlock():
global locked, timer_running
if not locked:
return
locked = False
timer_running = False
keyboard.unhook_all()
show_taskbar()
root.quit()
root.destroy()
# ======== 倒计时线程 ========
def countdown_timer(seconds):
global timer_running
timer_running = True
remaining = seconds
while remaining >= 0 and locked:
mins, secs = divmod(remaining, 60)
time_str = f"{mins:02d}:{secs:02d}"
root.after(0, lambda t=time_str: label_time.config(text=f"⏳ 剩余 {t}"))
time.sleep(1)
remaining -= 1
if locked:
root.after(0, unlock)
# ======== 启动白名单程序(支持自定义路径 + 激活已运行窗口)========
def launch_program(exe_name_no_ext):
"""启动白名单程序,如果已运行则激活其窗口"""
target_name = exe_name_no_ext + ".exe"
found_pid = None
for proc in psutil.process_iter(['pid', 'name']):
try:
if proc.info['name'].lower() == target_name.lower():
found_pid = proc.info['pid']
break
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
if found_pid:
def enum_callback(hwnd, lParam):
try:
_, pid = win32process.GetWindowThreadProcessId(hwnd)
if pid == found_pid and win32gui.IsWindowVisible(hwnd):
win32gui.SetForegroundWindow(hwnd)
if win32gui.IsIconic(hwnd):
win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
return False
except:
pass
return True
win32gui.EnumWindows(enum_callback, None)
print(f"[+] 已激活现有程序窗口:{target_name}")
else:
try:
if exe_name_no_ext in WHITELIST_PATHS:
subprocess.Popen(WHITELIST_PATHS[exe_name_no_ext])
print(f"[+] 已从指定路径启动白名单程序:{exe_name_no_ext}")
else:
subprocess.Popen([target_name], shell=True)
print(f"[+] 已启动白名单程序:{target_name}")
except Exception as e:
print(f"[-] 启动失败:{e}")
def on_listbox_select(event):
selection = listbox.curselection()
if selection:
idx = selection[0]
exe_name = listbox.get(idx)
launch_program(exe_name)
# ======== 日期更新函数 ========
def update_day_labels():
try:
# 计算从 DEFAULT_DATE 至今的天数
user_date = datetime.strptime(DEFAULT_DATE, "%Y-%m-%d")
days_diff = (datetime.now() - user_date).days
if days_diff >= 0:
day_text = f"已经过去了 {days_diff} 天"
else:
day_text = f"距离目标还有 {-days_diff} 天"
label_days.config(text=day_text)
# 计算毕业第10年天数
grad_date = datetime.strptime(GRADUATION_DATE, "%Y-%m-%d")
days_grad = (datetime.now() - grad_date).days
grad_text = f"毕业第10年-重获新生\n已经过去了 {days_grad} 天"
label_graduation.config(text=grad_text)
except ValueError:
label_days.config(text="日期格式错误")
label_graduation.config(text="日期格式错误")
# 每6小时更新一次
root.after(UPDATE_INTERVAL_MS, update_day_labels)
# ======== 创建主锁机窗口 ========
root = tk.Tk()
root.title("禅定空间 · Python 玩具版")
root.attributes('-fullscreen', True)
root.attributes('-topmost', False)
root.configure(bg='#1a1a2e')
root.overrideredirect(True)
main_frame = tk.Frame(root, bg='#1a1a2e')
main_frame.pack(expand=True, fill='both')
top_frame = tk.Frame(main_frame, bg='#1a1a2e')
top_frame.pack(side='top', fill='both', expand=True)
# 倒计时
label_time = tk.Label(top_frame, text="⏳ 剩余 00:00", font=("Segoe UI", 36),
fg='#f0c27f', bg='#1a1a2e')
label_time.pack(pady=(50, 10))
# 标题
label_title = tk.Label(top_frame, text="🧘 禅定中", font=("Segoe UI", 46),
fg='#eeeeee', bg='#1a1a2e')
label_title.pack(pady=(5, 15))
# 提示
label_hint = tk.Label(top_frame, text="F12 应急退出",
font=("Segoe UI", 18), fg='#888888', bg='#1a1a2e')
label_hint.pack()
# ----- 新增:日期天数显示(全部统一为红色华文行楷 28号加粗)-----
# 座右铭
label_motto = tk.Label(top_frame, text="第四次顿悟-有罪 感受痛苦",
font=("华文行楷", 28, "bold"), fg='#ff6b6b', bg='#1a1a2e')
label_motto.pack(pady=(25, 5))
# 天数差
label_days = tk.Label(top_frame, text="", font=("华文行楷", 28, "bold"),
fg='#ff6b6b', bg='#1a1a2e')
label_days.pack(pady=(5, 5))
# 毕业纪念
label_graduation = tk.Label(top_frame, text="", font=("华文行楷", 28, "bold"),
fg='#ff6b6b', bg='#1a1a2e')
label_graduation.pack(pady=(5, 10))
# 底部白名单区域
bottom_frame = tk.Frame(main_frame, bg='#1a1a2e')
bottom_frame.pack(side='bottom', fill='x', padx=50, pady=(0, 30))
label_launcher = tk.Label(bottom_frame, text="📋 可启动的程序(双击启动)",
font=("Segoe UI", 14), fg='#cccccc', bg='#1a1a2e')
label_launcher.pack(anchor='w')
listbox_frame = tk.Frame(bottom_frame, bg='#1a1a2e')
listbox_frame.pack(fill='x', pady=(6, 10))
listbox = tk.Listbox(listbox_frame, height=4, font=("Consolas", 12),
bg='#0f3460', fg='#e94560', selectbackground='#16213e',
relief='flat', borderwidth=0, highlightthickness=0)
for prog in WHITELIST:
listbox.insert(tk.END, prog)
listbox.pack(side='left', fill='x', expand=True)
listbox.bind('<Double-Button-1>', on_listbox_select)
btn_launch = tk.Button(bottom_frame, text="▶ 启动选中程序",
font=("Segoe UI", 11), bg='#0f3460', fg='#ffffff',
activebackground='#16213e', activeforeground='#e94560',
relief='flat', command=lambda: launch_program(listbox.get(tk.ACTIVE)))
btn_launch.pack(pady=(0, 5))
label_front = tk.Label(bottom_frame, text="前台:", font=("Segoe UI", 10),
fg='#555555', bg='#1a1a2e')
label_front.pack(pady=(8, 0))
# ======== 辅助函数:判断窗口是否为任务管理器或安全对话框 ========
def is_task_manager_window(hwnd):
try:
class_name = win32gui.GetClassName(hwnd)
title = win32gui.GetWindowText(hwnd)
if class_name in ("TaskManagerWindow", "Windows.UI.Core.CoreWindow"):
return True
if class_name == "#32770" and ("任务管理器" in title or "Windows 安全" in title):
return True
except:
pass
return False
# ======== 白名单轮询线程 ========
def poll_foreground():
global is_white_active
last_non_whitelist = None
non_whitelist_count = 0
minimized_windows = set()
lock_hwnd = root.winfo_id()
while locked:
try:
hwnd = win32gui.GetForegroundWindow()
_, pid = win32process.GetWindowThreadProcessId(hwnd)
proc = psutil.Process(pid)
fg_raw = proc.name().lower()
fg = fg_raw.replace('.exe', '')
root.after(0, lambda: label_front.config(text=f"前台:{fg_raw}"))
# ---- 任务管理器特殊处理 ----
if is_task_manager_window(hwnd):
is_white_active = False
try:
style = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
if style & win32con.WS_EX_TOPMOST:
new_style = style & ~win32con.WS_EX_TOPMOST
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, new_style)
win32gui.SetWindowPos(hwnd, 0, 0, 0, 0, 0,
win32con.SWP_NOMOVE | win32con.SWP_NOSIZE |
win32con.SWP_FRAMECHANGED | win32con.SWP_NOACTIVATE)
except:
pass
root.after(0, lambda: root.attributes('-topmost', True))
root.after(0, lambda: root.lift())
win32gui.SetWindowPos(hwnd, lock_hwnd, 0, 0, 0, 0,
win32con.SWP_NOMOVE | win32con.SWP_NOSIZE |
win32con.SWP_NOACTIVATE)
continue
# ---- 常规白名单/豁免判断 ----
is_allowed = (fg in WHITELIST) or (fg in EXEMPT_PROCESSES)
if is_allowed:
root.after(0, lambda: root.attributes('-topmost', False))
win32gui.SetWindowPos(lock_hwnd, hwnd, 0, 0, 0, 0,
win32con.SWP_NOMOVE | win32con.SWP_NOSIZE |
win32con.SWP_NOACTIVATE)
is_white_active = True
last_non_whitelist = None
non_whitelist_count = 0
if hwnd in minimized_windows:
minimized_windows.discard(hwnd)
else:
if is_white_active:
root.after(0, lambda: root.attributes('-topmost', True))
root.after(0, lambda: root.lift())
is_white_active = False
if hwnd in minimized_windows:
continue
if last_non_whitelist == fg:
non_whitelist_count += 1
else:
non_whitelist_count = 1
last_non_whitelist = fg
if non_whitelist_count >= 3:
win32gui.ShowWindow(hwnd, win32con.SW_MINIMIZE)
minimized_windows.add(hwnd)
root.focus_force()
root.lift()
print(f"[!] 已最小化非白名单程序:{fg_raw} (pid={pid})")
non_whitelist_count = 0
# ---- 定期扫描所有窗口,将任务管理器压到锁机窗口之后 ----
def push_taskmgr_below(hwnd_enum, lParam):
if win32gui.IsWindowVisible(hwnd_enum) and is_task_manager_window(hwnd_enum):
try:
style = win32gui.GetWindowLong(hwnd_enum, win32con.GWL_EXSTYLE)
if style & win32con.WS_EX_TOPMOST:
new_style = style & ~win32con.WS_EX_TOPMOST
win32gui.SetWindowLong(hwnd_enum, win32con.GWL_EXSTYLE, new_style)
win32gui.SetWindowPos(hwnd_enum, 0, 0, 0, 0, 0,
win32con.SWP_NOMOVE | win32con.SWP_NOSIZE |
win32con.SWP_FRAMECHANGED | win32con.SWP_NOACTIVATE)
except:
pass
win32gui.SetWindowPos(hwnd_enum, lock_hwnd, 0, 0, 0, 0,
win32con.SWP_NOMOVE | win32con.SWP_NOSIZE |
win32con.SWP_NOACTIVATE)
return True
win32gui.EnumWindows(push_taskmgr_below, None)
except Exception:
pass
time.sleep(0.3)
threading.Thread(target=poll_foreground, daemon=True).start()
# ======== 键盘钩子 ========
def on_key_event(e):
global locked
if not locked:
return True
if e.event_type == keyboard.KEY_DOWN:
if e.name == 'f12':
unlock()
return False
if e.name in ('left windows', 'right windows'):
return False
if keyboard.is_pressed('alt') and e.name == 'tab':
return False
if keyboard.is_pressed('ctrl') and e.name == 'esc':
return False
if keyboard.is_pressed('ctrl+shift') and e.name == 'esc':
return False
if keyboard.is_pressed('alt') and e.name == 'f4':
return False
if keyboard.is_pressed('ctrl') and keyboard.is_pressed('alt'):
return False
return True
keyboard.on_press(on_key_event, suppress=True)
# ======== 关闭窗口时的清理 ========
def on_closing():
global locked
if locked:
locked = False
keyboard.unhook_all()
show_taskbar()
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_closing)
# ======== 启动 ========
hide_taskbar()
threading.Thread(target=countdown_timer, args=(LOCK_DURATION_SECONDS,), daemon=True).start()
# 初始化日期显示并开始定时更新
update_day_labels()
try:
root.mainloop()
finally:
if locked:
locked = False
keyboard.unhook_all()
show_taskbar()