工具 影音

工具

电脑定时锁屏软件V1.0

更新时间: 2025-12-02      阅读 收藏
立即下载

小孩玩电脑没有时间概念,所以用AI弄了这个定时锁屏软件,点击开始之后窗口会自动隐藏,只能通过快捷键Ctal+Alt+N+M调出窗口,倒计时还有10秒的时间,会弹窗提示

电脑定时锁屏软件V1.0(图1)


下方是软件代码:

import tkinter as tk
from tkinter import messagebox, ttk
import threading
import time
import os
import sys
import ctypes
import keyboard
from datetime import datetime

class LockScreenApp:
def init(self, root):
self.root = root
self.root.title("电脑锁屏助手v1.0、吾爱首发")
self.root.geometry("400x350")
self.root.resizable(False, False)
self.root.attributes("-topmost", True)

  1.     # 设置窗口图标
  2.     try:
  3.         if hasattr(sys, '_MEIPASS'):
  4.             icon_path = os.path.join(sys._MEIPASS, 'icon.ico')
  5.         else:
  6.             icon_path = 'icon.ico'
  7.         if os.path.exists(icon_path):
  8.             self.root.iconbitmap(icon_path)
  9.     except Exception:
  10.         # 如果图标不存在或无法加载,忽略错误
  11.         pass
  12.     # 设置主题颜色 - 使用微信绿
  13.     self.bg_color = "#f0f0f0"
  14.     self.btn_color = "#07C160"  # 微信绿
  15.     self.btn_hover_color = "#06984e"  # 微信绿-深
  16.     self.text_color = "#333333"
  17.     self.root.configure(bg=self.bg_color)
  18.  
  19.     # 初始化变量
  20.     self.lock_timer = None
  21.     self.is_timer_running = False
  22.     self.remaining_time = 0
  23.     self.paused_time = 0
  24.     self.is_paused = False
  25.     self.last_error = None
  26.  
  27.     # 初始化窗口位置记忆
  28.     self.last_window_position = None
  29.  
  30.     # 创建GUI组件
  31.     self.create_widgets()
  32.  
  33.     # 设置全局热键
  34.     self.set_hotkey()
  35.  
  36.     # 创建系统托盘图标
  37.     self.create_tray_icon()
  38.  
  39. def create_widgets(self):
  40.     main_frame = ttk.Frame(self.root, padding="20")
  41.     main_frame.pack(fill=tk.BOTH, expand=True)
  42.     main_frame.configure(style="Main.TFrame")
  43.  
  44.     style = ttk.Style()
  45.     style.configure("Main.TFrame", background=self.bg_color)
  46.     style.configure("TLabel", background=self.bg_color, foreground=self.text_color)
  47.     style.configure("Title.TLabel", font=("SimHei", 16, "bold"), background=self.bg_color, foreground=self.text_color)
  48.     style.configure("Subtitle.TLabel", font=("SimHei", 10), background=self.bg_color, foreground="#666666")
  49.     style.configure("Status.TLabel", font=("SimHei", 10), background=self.bg_color, foreground=self.text_color)
  50.     style.configure("Hotkey.TLabel", font=("SimHei", 8), foreground="#666666", background=self.bg_color)
  51.     style.configure("TButton", font=("SimHei", 10))
  52.  
  53.     title_frame = ttk.Frame(main_frame)
  54.     title_frame.pack(fill=tk.X, pady=(0, 15))
  55.     title_frame.configure(style="Main.TFrame")
  56.  
  57.     title_label = ttk.Label(title_frame, text="电脑锁屏助手", style="Title.TLabel")
  58.     title_label.pack(side=tk.LEFT)
  59.  
  60.     def create_custom_button(parent, text, command, width=5):
  61.         btn = tk.Button(
  62.             parent,
  63.             text=text,
  64.             font=("SimHei", 11, "bold"),
  65.             bg=self.btn_color,
  66.             fg="white",
  67.             activebackground=self.btn_hover_color,
  68.             activeforeground="white",
  69.             relief=tk.RAISED,
  70.             bd=0,
  71.             highlightthickness=0,
  72.             padx=10,
  73.             pady=10,
  74.             width=width,
  75.             command=command
  76.         )
  77.         btn.configure(highlightbackground=self.btn_color, highlightcolor=self.btn_color, highlightthickness=0)
  78.         btn.bind("<Enter>", lambda e, b=btn: b.config(bg=self.btn_hover_color))
  79.         btn.bind("<Leave>", lambda e, b=btn: b.config(bg=self.btn_color))
  80.         btn.bind("<ButtonPress-1>", lambda e, b=btn: b.config(bg="#004080"))
  81.         btn.bind("<ButtonRelease-1>", lambda e, b=btn: b.config(bg=self.btn_hover_color))
  82.         return btn
  83.  
  84.     # 时间选择器区域 - 放在上面一行
  85.     time_select_frame = ttk.Frame(main_frame)
  86.     time_select_frame.pack(fill=tk.X, pady=15)
  87.     time_select_frame.configure(style="Main.TFrame")
  88.  
  89.     # 5分钟按钮
  90.     self.btn_5min = create_custom_button(time_select_frame, "5分钟", lambda: self.start_timer(5), width=3)
  91.     self.btn_5min.pack(side=tk.LEFT, padx=10, pady=5)
  92.  
  93.     # 10分钟按钮
  94.     self.btn_10min = create_custom_button(time_select_frame, "10分钟", lambda: self.start_timer(10), width=4)
  95.     self.btn_10min.pack(side=tk.LEFT, padx=10, pady=5)
  96.  
  97.     # 自定义时间输入区域
  98.     custom_frame = ttk.Frame(time_select_frame)
  99.     custom_frame.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=10)
  100.     custom_frame.configure(style="Main.TFrame")
  101.  
  102.     self.custom_time_var = tk.StringVar()
  103.     self.custom_time_entry = ttk.Entry(
  104.         custom_frame,
  105.         textvariable=self.custom_time_var,
  106.         width=4,
  107.         font=(("SimHei", 22))
  108.     )
  109.     self.custom_time_entry.pack(side=tk.LEFT, padx=(0, 5), pady=2)
  110.     self.custom_time_entry.bind("<KeyRelease>", self.validate_time_input)
  111.     self.custom_time_entry.bind("<Return>", lambda event: self.start_custom_timer())
  112.  
  113.     ttk.Label(custom_frame, text="分钟", font=(("SimHei", 20))).pack(side=tk.LEFT, padx=2)
  114.  
  115.     # 按钮操作区域 - 放在下面一行
  116.     action_frame = ttk.Frame(main_frame)
  117.     action_frame.pack(fill=tk.X, pady=10)
  118.     action_frame.configure(style="Main.TFrame")
  119.  
  120.     # 开始按钮
  121.     self.btn_start = create_custom_button(action_frame, "开始", self.start_custom_timer, width=6)
  122.     self.btn_start.pack(side=tk.LEFT, padx=10, pady=5)
  123.  
  124.     # 暂停/继续按钮
  125.     self.btn_pause = create_custom_button(action_frame, "暂停/继续", self.toggle_pause, width=8)
  126.     self.btn_pause.pack(side=tk.LEFT, padx=10, pady=5)
  127.  
  128.     # 新增清空按钮
  129.     self.btn_clear = create_custom_button(action_frame, "清空", self.cancel_timer, width=6)
  130.     self.btn_clear.pack(side=tk.LEFT, padx=10, pady=5)
  131.  
  132.     status_frame = ttk.Frame(main_frame)
  133.     status_frame.pack(fill=tk.X, pady=15)
  134.     status_frame.configure(style="Main.TFrame")
  135.  
  136.     ttk.Label(status_frame, text="状态:", style="TLabel").pack(side=tk.LEFT)
  137.     self.status_var = tk.StringVar()
  138.     self.status_var.set("就绪")
  139.     self.status_label = ttk.Label(status_frame, textvariable=self.status_var, style="Status.TLabel")
  140.     self.status_label.pack(side=tk.LEFT, padx=5)
  141.  
  142.     bottom_frame = ttk.Frame(main_frame)
  143.     bottom_frame.pack(fill=tk.X, side=tk.BOTTOM)
  144.     bottom_frame.configure(style="Main.TFrame")
  145.  
  146.     hotkey_label = ttk.Label(bottom_frame, text="Ctrl+Alt+N+M 调出窗口", style="Hotkey.TLabel")
  147.     hotkey_label.pack(pady=(10, 0))
  148.  
  149. def start_timer(self, minutes):
  150.     """启动倒计时计时器"""
  151.     try:
  152.         if self.is_timer_running:
  153.             # 取消当前计时器
  154.             self.cancel_timer()
  155.  
  156.         # 设置新的倒计时时间
  157.         self.remaining_time = minutes * 60
  158.         self.is_timer_running = True
  159.         self.is_paused = False
  160.  
  161.         # 更新状态
  162.         self.status_var.set(f"锁屏将在 {minutes} 分钟后启动")
  163.         self.update_tray_tooltip(f"锁屏将在 {minutes} 分钟后启动")
  164.  
  165.         # 记录启动事件
  166.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  167.             f.write(f"计时器启动时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}, 设定时间: {minutes}分钟\n")
  168.  
  169.         # 创建并启动计时器线程
  170.         self.lock_timer = threading.Thread(target=self.countdown)
  171.         self.lock_timer.daemon = True
  172.         self.lock_timer.start()
  173.  
  174.         # 隐藏窗口
  175.         self.hide_window()
  176.     except Exception as e:
  177.         # 记录启动错误
  178.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  179.             f.write(f"启动计时器错误: {str(e)}\n")
  180.         messagebox.showerror("错误", f"启动计时器时出错: {str(e)}")
  181.  
  182. def validate_time_input(self, event=None):
  183.     """验证时间输入,只允许数字和小数点,最多480分钟"""
  184.     input_text = self.custom_time_var.get()
  185.  
  186.     # 移除非数字和小数点的字符
  187.     new_text = ''.join(c for c in input_text if c.isdigit() or c == '.')
  188.  
  189.     # 确保只有一个小数点
  190.     if new_text.count('.') > 1:
  191.         parts = new_text.split('.')
  192.         new_text = parts[0] + '.' + ''.join(parts[1:])
  193.  
  194.     # 更新输入框
  195.     if new_text != input_text:
  196.         self.custom_time_var.set(new_text)
  197.         # 保持光标位置
  198.         pos = event.widget.index(tk.insert)
  199.         event.widget.icursor(pos - (len(input_text) - len(new_text)))
  200.  
  201.     # 检查是否超过480分钟(8小时)
  202.     try:
  203.         if new_text:
  204.             minutes = float(new_text)
  205.             if minutes > 480:
  206.                 self.custom_time_var.set('480')
  207.                 self.status_var.set("警告: 超过最大时间限制")
  208.             else:
  209.                 self.status_var.set("就绪")
  210.     except ValueError:
  211.         pass
  212.  
  213. def start_custom_timer(self):
  214.     """从输入框启动自定义时间计时"""
  215.     try:
  216.         time_str = self.custom_time_var.get()
  217.         if not time_str:
  218.             messagebox.showwarning("输入错误", "请输入时间")
  219.             return
  220.  
  221.         minutes = float(time_str)
  222.         if minutes <= 0:
  223.             messagebox.showwarning("输入错误", "请输入大于0的时间")
  224.             return
  225.  
  226.         if minutes > 480:
  227.             messagebox.showwarning("输入错误", "最大时间为480分钟")
  228.             return
  229.  
  230.         # 保留浮点数,但设置最小时间为0.1分钟(6秒)
  231.         if minutes < 0.1:
  232.             minutes = 0.1  # 最少0.1分钟
  233.  
  234.         self.start_timer(minutes)
  235.     except ValueError:
  236.         messagebox.showwarning("输入错误", "请输入有效的数字")
  237.         self.custom_time_entry.focus_set()
  238.  
  239. def toggle_pause(self):
  240.     """暂停或恢复计时器"""
  241.     if not self.is_timer_running:
  242.         messagebox.showinfo("提示", "计时器未运行")
  243.         return
  244.  
  245.     if self.is_paused:
  246.         # 恢复计时器
  247.         self.is_paused = False
  248.         self.btn_pause.config(text="暂停/继续")
  249.         self.btn_pause.config(bg=self.btn_color, fg="white", activebackground=self.btn_hover_color)
  250.         time_text = self.format_time(self.remaining_time)
  251.         self.status_var.set(f"恢复倒计时,剩余时间: {time_text}")
  252.         self.update_tray_tooltip(f"恢复倒计时: {time_text}")
  253.         # 继续倒计时线程
  254.         self.lock_timer = threading.Thread(target=self.countdown)
  255.         self.lock_timer.daemon = True
  256.         self.lock_timer.start()
  257.         # 记录恢复事件
  258.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  259.             f.write(f"计时器恢复时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}, 剩余时间: {time_text}\n")
  260.     else:
  261.         # 暂停计时器
  262.         self.is_paused = True
  263.         self.btn_pause.config(text="继续")
  264.         self.btn_pause.config(bg="#ffc107", fg="#333333", activebackground="#e0a800")
  265.         time_text = self.format_time(self.remaining_time)
  266.         self.status_var.set(f"已暂停,剩余时间: {time_text}")
  267.         self.update_tray_tooltip(f"已暂停: {time_text}")
  268.         # 记录暂停事件
  269.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  270.             f.write(f"计时器暂停时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}, 剩余时间: {time_text}\n")
  271.  
  272. def countdown(self):
  273.     """倒计时线程函数"""
  274.     try:
  275.         # 记录倒计时开始
  276.         start_time = time.time()
  277.         target_time = start_time + self.remaining_time
  278.         # 清除可能存在的警告窗口引用
  279.         if hasattr(self, '_warning_window'):
  280.             if self._warning_window.winfo_exists():
  281.                 self._warning_window.destroy()
  282.  
  283.         while self.is_timer_running and not self.is_paused:
  284.             # 计算剩余时间(更准确的计时方式
  285.             current_time = time.time()
  286.             self.remaining_time = int(target_time - current_time)
  287.  
  288.             if self.remaining_time <= 0:
  289.                 break
  290.  
  291.             # 更新状态和托盘提示
  292.             time_text = self.format_time(self.remaining_time)
  293.  
  294.             # 使用线程安全的方式更新GUI
  295.             self.root.after(0, lambda tt=time_text: self.status_var.set(f"剩余时间: {tt}"))
  296.             self.update_tray_tooltip(f"剩余时间: {time_text}")
  297.  
  298.             # 添加倒计时提示功能(10秒及以内)
  299.             if 0 < self.remaining_time <= 10:
  300.                 # 使用线程安全的方式显示或更新提示框
  301.                 self.root.after(0, lambda remaining=self.remaining_time: self._show_lock_warning(remaining))
  302.  
  303.             # 休眠1秒,但可以被中断
  304.             for _ in range(10):  # 分成10次小休眠,以便更快响应暂停/取消
  305.                 if not self.is_timer_running or self.is_paused:
  306.                     break
  307.                 time.sleep(0.1)
  308.  
  309.             # 检查是否被暂停或取消
  310.             if not self.is_timer_running or self.is_paused:
  311.                 break
  312.  
  313.         # 倒计时结束,执行锁屏
  314.         if self.remaining_time <= 0 and self.is_timer_running and not self.is_paused:
  315.             self.lock_screen()
  316.     except Exception as e:
  317.         # 记录倒计时错误
  318.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  319.             f.write(f"倒计时错误: {str(e)}\n")
  320.         # 尝试锁屏作为安全措施
  321.         try:
  322.             self.lock_screen()
  323.         except:
  324.             pass
  325.  
  326. def format_time(self, seconds):
  327.     """格式化时间为分:秒"""
  328.     minutes = seconds // 60
  329.     secs = seconds % 60
  330.     return f"{minutes:02d}:{secs:02d}"
  331.  
  332. def _show_lock_warning(self, remaining):
  333.     """显示锁屏前的警告提示,支持动态更新倒计时"""
  334.     # 检查是否已存在警告窗口,如果存在则更新内容,否则创建新窗口
  335.     if hasattr(self, '_warning_window') and self._warning_window.winfo_exists():
  336.         # 更新现有窗口的标签文本
  337.         if hasattr(self, '_warning_label'):
  338.             self._warning_label.config(text=f"电脑还有 {remaining} 秒锁屏了")
  339.     else:
  340.         # 创建一个独立的提示窗口
  341.         self._warning_window = tk.Toplevel(self.root)
  342.         self._warning_window.title("锁屏警告")
  343.         self._warning_window.geometry("300x150")
  344.         self._warning_window.attributes("-topmost", True)
  345.         self._warning_window.configure(bg="#f0f0f0")
  346.  
  347.         # 居中窗口
  348.         self._warning_window.update_idletasks()
  349.         width = self._warning_window.winfo_width()
  350.         height = self._warning_window.winfo_height()
  351.         x = (self._warning_window.winfo_screenwidth() // 2) - (width // 2)
  352.         y = (self._warning_window.winfo_screenheight() // 2) - (height // 2)
  353.         self._warning_window.geometry(f"{width}x{height}+{x}+{y}")
  354.  
  355.         # 添加提示标签
  356.         self._warning_label = tk.Label(
  357.             self._warning_window,
  358.             text=f"电脑还有 {remaining} 秒锁屏了",
  359.             font=("SimHei", 16, "bold"),
  360.             bg="#f0f0f0",
  361.             fg="#ff0000"
  362.         )
  363.         self._warning_label.pack(pady=20)
  364.  
  365.         # 添加关闭按钮
  366.         btn_ok = tk.Button(
  367.             self._warning_window,
  368.             text="知道了",
  369.             font=("SimHei", 12),
  370.             bg=self.btn_color,
  371.             fg="white",
  372.             activebackground=self.btn_hover_color,
  373.             relief=tk.RAISED,
  374.             bd=0,
  375.             padx=20,
  376.             pady=8,
  377.             command=self._warning_window.destroy
  378.         )
  379.         btn_ok.pack(pady=10)
  380.         btn_ok.configure(highlightbackground=self.btn_color, highlightthickness=0)
  381.  
  382. def lock_screen(self):
  383.     """锁定屏幕(支持多种锁屏方式作为备选)"""
  384.     try:
  385.         # 记录锁屏时间
  386.         lock_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  387.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  388.             f.write(f"屏幕锁定时间: {lock_time}\n")
  389.  
  390.         # 方法1: 使用Windows API (首选方法)
  391.         try:
  392.             result = ctypes.windll.user32.LockWorkStation()
  393.             if result:
  394.                 with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  395.                     f.write("锁屏成功: 使用Windows API\n")
  396.             else:
  397.                 raise Exception("LockWorkStation API 调用失败")
  398.         except Exception as e1:
  399.             # 记录首选方法失败
  400.             with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  401.                 f.write(f"首选锁屏方法失败: {str(e1)}\n")
  402.  
  403.             # 方法2: 使用rundll32命令
  404.             try:
  405.                 import subprocess
  406.                 subprocess.run(["rundll32.exe", "user32.dll,LockWorkStation"],
  407.                               shell=True, check=True)
  408.                 with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  409.                     f.write("锁屏成功: 使用rundll32命令\n")
  410.             except Exception as e2:
  411.                 # 记录方法2失败
  412.                 with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  413.                     f.write(f"备用锁屏方法失败: {str(e2)}\n")
  414.  
  415.                 # 方法3: 使用PowerShell命令
  416.                 try:
  417.                     import subprocess
  418.                     powershell_command = "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait('^({ESC}{TAB}{ESC})')"
  419.                     subprocess.run(["powershell.exe", "-Command", powershell_command],
  420.                                   shell=True, check=True)
  421.                     with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  422.                         f.write("锁屏成功: 使用PowerShell命令\n")
  423.                 except Exception as e3:
  424.                     # 所有方法都失败
  425.                     with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  426.                         f.write(f"所有锁屏方法都失败: {str(e3)}\n")
  427.  
  428.                     # 显示消息提示用户手动锁屏
  429.                     messagebox.showwarning(
  430.                         "锁屏失败",
  431.                         "无法自动锁定屏幕。请手动锁定您的计算机。\n" +
  432.                         "锁屏时间: " + lock_time
  433.                     )
  434.  
  435.         # 重置状态
  436.         self.reset_timer()
  437.  
  438.     except Exception as e:
  439.         # 记录总错误
  440.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  441.             f.write(f"锁屏过程总错误: {str(e)}\n")
  442.  
  443.         # 即使出错也要重置状态
  444.         self.reset_timer()
  445.  
  446. def reset_timer(self):
  447.     """重置计时器状态"""
  448.     self.is_timer_running = False
  449.     self.is_paused = False
  450.     self.remaining_time = 0
  451.     self.btn_pause.config(text="暂停")
  452.     self.status_var.set("就绪")
  453.     self.update_tray_tooltip("就绪")
  454.  
  455. def cancel_timer(self):
  456.     """取消当前计时器"""
  457.     # 确保线程安全地停止
  458.     self.is_timer_running = False
  459.     self.is_paused = False
  460.     self.remaining_time = 0
  461.  
  462.     # 重置UI状态
  463.     self.btn_pause.config(text="暂停")
  464.     self.status_var.set("就绪")
  465.     self.update_tray_tooltip("就绪")
  466.  
  467.     # 如果有正在运行的计时器线程,尝试让它自然结束
  468.     # 注意:Python中不能强制终止线程,而是通过标志位让它自己退出
  469.  
  470.     # 额外确保界面可见,用户能看到取消后的状态
  471.     self.show_window()
  472.  
  473.     # 记录取消事件
  474.     try:
  475.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  476.             f.write(f"计时器取消时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
  477.     except Exception as e:
  478.         # 即使日志写入失败,也要确保功能正常
  479.         pass
  480.  
  481. def hide_window(self):
  482.     """隐藏窗口"""
  483.     # 保存当前窗口位置
  484.     try:
  485.         x = self.root.winfo_x()
  486.         y = self.root.winfo_y()
  487.         if x > 0 and y > 0:  # 确保位置有效
  488.             self.last_window_position = (x, y)
  489.     except:
  490.         pass  # 忽略获取位置时的错误
  491.  
  492.     # 完全隐藏窗口(不仅是最小化)
  493.     self.root.withdraw()
  494.     # 在系统托盘显示消息
  495.     try:
  496.         self.tray_icon.showmessage(
  497.             "锁屏助手",
  498.             "程序已在后台运行\n按 Ctrl+Alt+N+M 调出窗口",
  499.             timeout=5000
  500.         )
  501.     except:
  502.         pass  # 忽略托盘错误
  503.  
  504. def show_window(self):
  505.     """显示窗口"""
  506.     try:
  507.         # 从隐藏状态恢复
  508.         self.root.deiconify()
  509.         # 确保窗口在最上层
  510.         self.root.attributes("-topmost", True)
  511.         self.root.attributes("-topmost", False)  # 允许其他窗口也能成为顶层
  512.         # 激活窗口
  513.         self.root.focus_force()
  514.  
  515.         # 检查是否有保存的窗口位置,如果没有则居中显示
  516.         if not hasattr(self, 'last_window_position'):
  517.             # 计算屏幕中心位置
  518.             screen_width = self.root.winfo_screenwidth()
  519.             screen_height = self.root.winfo_screenheight()
  520.             window_width = 400  # 窗口宽度
  521.             window_height = 350  # 窗口高度
  522.  
  523.             x = (screen_width - window_width) // 2
  524.             y = (screen_height - window_height) // 2
  525.  
  526.             # 设置窗口位置并保存
  527.             self.root.geometry(f"+{x}+{y}")
  528.             self.last_window_position = (x, y)
  529.         else:
  530.             # 使用之前保存的位置
  531.             x, y = self.last_window_position
  532.             self.root.geometry(f"+{x}+{y}")
  533.     except Exception as e:
  534.         # 记录错误但不显示,避免影响用户体验
  535.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  536.             f.write(f"显示窗口错误: {str(e)}\n")
  537.  
  538. def create_tray_icon(self):
  539.     """创建系统托盘图标"""
  540.     try:
  541.         # 尝试导入并创建系统托盘图标
  542.         import pystray
  543.         from pystray import MenuItem as item
  544.         from PIL import Image, ImageDraw
  545.  
  546.         # 创建一个简单的图标
  547.         def create_image():
  548.             width = 64
  549.             height = 64
  550.             color1 = "#0078d7"
  551.             color2 = "white"
  552.  
  553.             # 创建空白图像
  554.             image = Image.new('RGB', (width, height), color1)
  555.             dc = ImageDraw.Draw(image)
  556.  
  557.             # 绘制简单的锁图标
  558.             dc.rectangle([10, 25, 54, 45], fill=color2)
  559.             dc.rectangle([25, 15, 39, 35], fill=color2)
  560.             dc.ellipse([20, 10, 44, 20], fill=color1, outline=color2, width=3)
  561.  
  562.             return image
  563.  
  564.         # 创建菜单
  565.         menu = (
  566.             item('显示窗口', self.show_window),
  567.             item('暂停/恢复', self.toggle_pause),
  568.             item('退出', self.on_closing)
  569.         )
  570.  
  571.         # 创建托盘图标
  572.         self.tray_icon = pystray.Icon("LockScreen", create_image(), "锁屏助手", menu)
  573.  
  574.         # 在单独的线程中运行托盘图标
  575.         self.tray_thread = threading.Thread(target=self.tray_icon.run, daemon=True)
  576.         self.tray_thread.start()
  577.     except ImportError:
  578.         # 如果没有安装pystray,使用tkinter的简化方法
  579.         self.tray_icon = None
  580.         pass
  581.  
  582. def update_tray_tooltip(self, message):
  583.     """更新系统托盘提示文本"""
  584.     try:
  585.         if hasattr(self, 'tray_icon') and self.tray_icon:
  586.             self.tray_icon.title = f"锁屏助手 - {message}"
  587.     except:
  588.         pass  # 忽略托盘错误
  589.  
  590. def set_hotkey(self):
  591.     """设置全局热键"""
  592.     try:
  593.         # 移除可能已存在的热键(避免重复设置)
  594.         try:
  595.             keyboard.remove_hotkey('ctrl+alt+n+m')
  596.         except:
  597.             pass
  598.  
  599.         # 设置组合热键 Ctrl+Alt+N+M
  600.         keyboard.add_hotkey('ctrl+alt+n+m', self.show_window)
  601.  
  602.         # 记录热键设置成功
  603.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  604.             f.write(f"热键设置成功: Ctrl+Alt+N+M\n")
  605.  
  606.     except Exception as e:
  607.         # 记录错误
  608.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  609.             f.write(f"热键设置失败: {str(e)}\n")
  610.  
  611.         # 尝试使用备用方案
  612.         try:
  613.             # 备用方案:使用全局钩子监听按键事件
  614.             def on_key_event(event):
  615.                 # 检查是否按下了Ctrl+Alt+N+M组合键
  616.                 if event.name == 'm' and keyboard.is_pressed('ctrl') and keyboard.is_pressed('alt') and keyboard.is_pressed('n'):
  617.                     self.show_window()
  618.  
  619.             # 监听所有按键事件
  620.             keyboard.on_press(on_key_event)
  621.  
  622.             # 记录备用方案设置成功
  623.             with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  624.                 f.write("备用热键方案设置成功\n")
  625.  
  626.         except Exception as e2:
  627.             # 记录备用方案失败
  628.             with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  629.                 f.write(f"备用热键方案设置失败: {str(e2)}\n")
  630.  
  631.             # 显示警告消息
  632.             messagebox.showwarning(
  633.                 "热键设置警告",
  634.                 "无法设置全局热键。请确保以管理员权限运行程序。\n" +
  635.                 "您仍然可以通过系统托盘图标访问程序。"
  636.             )
  637.  
  638. def on_closing(self):
  639.     """窗口关闭事件处理"""
  640.     # 取消计时器
  641.     self.cancel_timer()
  642.     # 清理热键
  643.     try:
  644.         keyboard.unhook_all()
  645.     except:
  646.         pass
  647.     # 关闭托盘图标
  648.     try:
  649.         if hasattr(self, 'tray_icon') and self.tray_icon:
  650.             self.tray_icon.stop()
  651.     except:
  652.         pass
  653.     # 记录程序退出
  654.     with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  655.         f.write(f"程序退出时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
  656.         f.write("="*50 + "\n")
  657.     # 关闭窗口
  658.     self.root.destroy()
  659.  
  660. def check_environment(self):
  661.     """检查运行环境"""
  662.     try:
  663.         # 创建日志目录(如果不存在)
  664.         log_file = "lock_screen_log.txt"
  665.  
  666.         # 写入程序启动信息
  667.         with open(log_file, "a", encoding="utf-8") as f:
  668.             f.write("="*50 + "\n")
  669.             f.write(f"程序启动时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
  670.             f.write(f"Python版本: {sys.version}\n")
  671.             f.write(f"操作系统: Windows\n")
  672.  
  673.         # 检查是否以管理员权限运行
  674.         try:
  675.             is_admin = ctypes.windll.shell32.IsUserAnAdmin()
  676.             with open(log_file, "a", encoding="utf-8") as f:
  677.                 f.write(f"管理员权限: {'是' if is_admin else '否'}\n")
  678.         except:
  679.             with open(log_file, "a", encoding="utf-8") as f:
  680.                 f.write("无法检查管理员权限\n")
  681.  
  682.     except Exception as e:
  683.         # 如果日志写入失败,尝试简单的异常处理
  684.         self.last_error = str(e)
  685.         pass
复制代码


  1.     try:
  2.         with open("lock_screen_log.txt", "a", encoding="utf-8") as f:
  3.             f.write(f"未捕获异常: {exc_type.__name__}: {str(exc_value)}\n")
  4.             import traceback
  5.             traceback.print_tb(exc_traceback, file=f)
  6.             f.write("="*50 + "\n")
  7.     except:
  8.         pass  # 如果日志写入失败,忽略
  9.  
  10. # 设置全局异常处理
  11. sys.excepthook = handle_exception
复制代码
  1. root = tk.Tk()
  2. # 创建应用实例
  3. app = LockScreenApp(root)
  4. # 运行应用
  5. root.mainloop()
复制代码


- THE END -
取消
微信二维码
微信二维码
支付宝二维码
最新推荐
推荐标签