import tkinter as tk
from tkinter import messagebox, simpledialog, font
import win32api
import win32con
import win32gui
import sys
import os
import time
import math
import json
from datetime import datetime, timedelta
from threading import Thread
from PIL import Image, ImageDraw, ImageFont, ImageTk
import ctypes
import random
class FireworkParticle:
"""烟花粒子类"""
def __init__(self, x, y, color, velocity_x, velocity_y, life_time, gravity=0.1):
self.x = x
self.y = y
self.color = color
self.velocity_x = velocity_x
self.velocity_y = velocity_y
self.life_time = life_time
self.age = 0
self.gravity = gravity
self.size = random.uniform(1.5, 3.0)
self.alpha = 255
def update(self, delta_time):
"""更新粒子状态"""
self.age += delta_time
self.velocity_y += self.gravity
self.x += self.velocity_x
self.y += self.velocity_y
progress = self.age / self.life_time
self.alpha = int(255 * (1 - progress))
return self.age < self.life_time
def draw(self, draw):
"""绘制粒子"""
if self.alpha > 0:
r, g, b = self.color
draw.ellipse([self.x - self.size, self.y - self.size, self.x + self.size, self.y + self.size], fill=(r, g, b, self.alpha))
class Firework:
"""烟花类"""
def __init__(self, x, y, color, explosion_height, particle_count=80):
self.x = x
self.y = y
self.color = color
self.explosion_height = explosion_height
self.particle_count = particle_count
self.state = "rising"
self.velocity_y = -random.uniform(8, 12)
self.particles = []
self.creation_time = time.time()
def update(self, delta_time):
"""更新烟花状态"""
if self.state == "rising":
self.y += self.velocity_y
if self.y <= self.explosion_height:
self.explode()
self.state = "exploding"
elif self.state == "exploding":
alive_particles = []
for particle in self.particles:
if particle.update(delta_time):
alive_particles.append(particle)
self.particles = alive_particles
if not self.particles and time.time() - self.creation_time > 3:
self.state = "done"
return self.state != "done"
def explode(self):
"""烟花爆炸"""
for _ in range(self.particle_count):
angle = random.uniform(0, 2 * math.pi)
speed = random.uniform(3, 8)
velocity_x = math.cos(angle) * speed
velocity_y = math.sin(angle) * speed
life_time = random.uniform(1.5, 3.0)
color_variation = random.randint(-30, 30)
r = max(0, min(255, self.color[0] + color_variation))
g = max(0, min(255, self.color[1] + color_variation))
b = max(0, min(255, self.color[2] + color_variation))
particle = FireworkParticle(self.x, self.y, (r, g, b), velocity_x, velocity_y, life_time)
self.particles.append(particle)
def draw(self, draw):
"""绘制烟花"""
if self.state == "rising":
trail_length = 20
for i in range(trail_length):
alpha = int(255 * (1 - i / trail_length))
size = max(1, 3 - i * 0.1)
draw.ellipse([self.x - size, self.y + i * 2 - size, self.x + size, self.y + i * 2 + size], fill=(*self.color, alpha))
elif self.state == "exploding":
for particle in self.particles:
particle.draw(draw)
class TaskItem:
"""任务事项类"""
def __init__(self, text, completed=False, created_time=None):
self.text = text
self.completed = completed
self.created_time = created_time or datetime.now()
def to_dict(self):
"""转换为字典"""
return {"text": self.text, "completed": self.completed, "created_time": self.created_time.isoformat()}
@classmethod
def from_dict(cls, data):
"""从字典创建"""
return cls(text=data["text"], completed=data["completed"], created_time=datetime.fromisoformat(data["created_time"]))
class FireworkWallpaper:
def __init__(self):
self.root = tk.Tk()
self.root.title("烟花任务壁纸")
self.root.geometry("800x600")
self.screen_width = self.root.winfo_screenwidth()
self.screen_height = self.root.winfo_screenheight()
self.wallpaper_hwnd = None
self.is_running = False
self.fireworks = []
self.last_firework_time = 0
self.firework_interval = 2.0
self.tasks = []
self.tasks_file = os.path.join(os.path.dirname(__file__), "tasks.json")
self.load_tasks()
self.effects = {'fireworks': True, 'tasks_display': True, 'date_display': True, 'glow_effects': True}
self.firework_colors = [
(255, 107, 107),
(78, 205, 196),
(255, 234, 167),
(198, 108, 132),
(86, 98, 246),
(255, 159, 28),
(156, 39, 176),
]
self.setup_ui()
def setup_ui(self):
"""设置用户界面"""
self.root.configure(bg='#1a1a2e')
title = tk.Label(self.root, text="🎆 烟花任务壁纸系统", font=("微软雅黑", 24, "bold"), fg="#e94560", bg="#1a1a2e")
title.pack(pady=20)
main_frame = tk.Frame(self.root, bg="#16213e")
main_frame.pack(fill="both", expand=True, padx=20, pady=10)
left_frame = tk.Frame(main_frame, bg="#16213e")
left_frame.pack(side="left", fill="both", expand=True, padx=(0, 10))
effects_frame = tk.LabelFrame(left_frame, text="🎨 效果设置", font=("微软雅黑", 12, "bold"), fg="#0f3460", bg="#16213e", padx=10, pady=10)
effects_frame.pack(fill="x", pady=5)
self.effect_vars = {}
for effect, enabled in self.effects.items():
var = tk.BooleanVar(value=enabled)
self.effect_vars[effect] = var
effect_name = {'fireworks': '烟花效果', 'tasks_display': '任务显示', 'date_display': '日期显示', 'glow_effects': '发光效果'}[effect]
cb = tk.Checkbutton(effects_frame, text=effect_name, variable=var, font=("微软雅黑", 10), fg="#e94560", bg="#16213e", selectcolor="#1a1a2e", activebackground="#16213e", activeforeground="#e94560")
cb.pack(anchor="w", pady=5)
tasks_frame = tk.LabelFrame(left_frame, text="📝 任务管理", font=("微软雅黑", 12, "bold"), fg="#0f3460", bg="#16213e", padx=10, pady=10)
tasks_frame.pack(fill="both", expand=True, pady=5)
task_input_frame = tk.Frame(tasks_frame, bg="#16213e")
task_input_frame.pack(fill="x", pady=5)
self.task_entry = tk.Entry(task_input_frame, font=("微软雅黑", 10), bg="#0f3460", fg="white", insertbackground="white")
self.task_entry.pack(side="left", fill="x", expand=True, padx=(0, 5))
self.task_entry.bind("<Return>", lambda e: self.add_task())
tk.Button(task_input_frame, text="添加", command=self.add_task, font=("微软雅黑", 9), bg="#e94560", fg="white", relief="flat").pack(side="right")
self.task_listbox = tk.Listbox(tasks_frame, font=("微软雅黑", 10), bg="#0f3460", fg="white", selectbackground="#e94560", selectforeground="white", height=8)
self.task_listbox.pack(fill="both", expand=True, pady=5)
self.update_task_listbox()
task_buttons_frame = tk.Frame(tasks_frame, bg="#16213e")
task_buttons_frame.pack(fill="x")
tk.Button(task_buttons_frame, text="标记完成", command=self.mark_task_completed, font=("微软雅黑", 9), bg="#27ae60", fg="white", relief="flat").pack(side="left", padx=2)
tk.Button(task_buttons_frame, text="删除", command=self.delete_task, font=("微软雅黑", 9), bg="#e74c3c", fg="white", relief="flat").pack(side="left", padx=2)
tk.Button(task_buttons_frame, text="清空", command=self.clear_tasks, font=("微软雅黑", 9), bg="#f39c12", fg="white", relief="flat").pack(side="left", padx=2)
right_frame = tk.Frame(main_frame, bg="#16213e")
right_frame.pack(side="right", fill="both", expand=True, padx=(10, 0))
preview_frame = tk.LabelFrame(right_frame, text="👁️ 效果预览", font=("微软雅黑", 12, "bold"), fg="#0f3460", bg="#16213e", padx=10, pady=10)
preview_frame.pack(fill="both", expand=True, pady=5)
self.preview_canvas = tk.Canvas(preview_frame, width=300, height=200, bg="#0f3460", highlightthickness=0)
self.preview_canvas.pack(fill="both", expand=True)
control_frame = tk.Frame(right_frame, bg="#16213e")
control_frame.pack(fill="x", pady=10)
tk.Button(control_frame, text="🎆 启动烟花壁纸", command=self.start_firework_wallpaper, font=("微软雅黑", 12, "bold"), bg="#e94560", fg="white", padx=20, pady=10, relief="flat", cursor="hand2").pack(fill="x", pady=5)
tk.Button(control_frame, text="停止壁纸", command=self.stop_wallpaper, font=("微软雅黑", 11), bg="#e74c3c", fg="white", padx=20, pady=8, relief="flat", cursor="hand2").pack(fill="x", pady=2)
self.status_label = tk.Label(control_frame, text="就绪", font=("微软雅黑", 10), fg="#95a5a6", bg="#16213e")
self.status_label.pack(pady=5)
info_text = """使用说明:
• 添加今日任务事项,壁纸上会显示
• 烟花效果会自动随机发射
• 启动后可以最小化此窗口
• 任务数据会自动保存"""
info = tk.Label(control_frame, text=info_text, font=("微软雅黑", 9), fg="#bdc3c7", bg="#16213e", justify="left")
info.pack(pady=10)
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
self.start_preview_animation()
def start_preview_animation(self):
"""启动预览动画"""
def animate():
self.preview_canvas.delete("all")
self.preview_canvas.create_rectangle(0, 0, 300, 200, fill="#0f3460", outline="")
current_time = time.time()
self.preview_canvas.create_oval(140, 150, 160, 170, fill="#e94560", outline="")
for i in range(8):
angle = i * math.pi / 4
x = 150 + 30 * math.cos(angle)
y = 100 + 30 * math.sin(angle)
self.preview_canvas.create_oval(x-3, y-3, x+3, y+3, fill="#ffd700", outline="")
self.preview_canvas.create_text(150, 50, text="今日任务预览", fill="white", font=("微软雅黑", 10))
self.root.after(2000, animate)
animate()
def load_tasks(self):
"""加载任务数据"""
try:
if os.path.exists(self.tasks_file):
with open(self.tasks_file, 'r', encoding='utf-8') as f:
data = json.load(f)
self.tasks = [TaskItem.from_dict(item) for item in data]
except Exception as e:
print(f"加载任务失败:{e}")
self.tasks = []
def save_tasks(self):
"""保存任务数据"""
try:
data = [task.to_dict() for task in self.tasks]
with open(self.tasks_file, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"保存任务失败:{e}")
def add_task(self):
"""添加任务"""
text = self.task_entry.get().strip()
if text:
task = TaskItem(text)
self.tasks.append(task)
self.task_entry.delete(0, tk.END)
self.update_task_listbox()
self.save_tasks()
def mark_task_completed(self):
"""标记任务为完成"""
selection = self.task_listbox.curselection()
if selection:
index = selection[0]
self.tasks[index].completed = not self.tasks[index].completed
self.update_task_listbox()
self.save_tasks()
def delete_task(self):
"""删除任务"""
selection = self.task_listbox.curselection()
if selection:
index = selection[0]
self.tasks.pop(index)
self.update_task_listbox()
self.save_tasks()
def clear_tasks(self):
"""清空所有任务"""
if messagebox.askyesno("确认", "确定要清空所有任务吗?"):
self.tasks = []
self.update_task_listbox()
self.save_tasks()
def update_task_listbox(self):
"""更新任务列表显示"""
self.task_listbox.delete(0, tk.END)
for task in self.tasks:
status = "✓" if task.completed else "○"
display_text = f"{status}{task.text}"
self.task_listbox.insert(tk.END, display_text)
if task.completed:
self.task_listbox.itemconfig(tk.END, {'fg': '#95a5a6'})
def start_firework_wallpaper(self):
"""启动烟花壁纸"""
if self.is_running:
self.status_label.config(text="壁纸已在运行", fg="#f39c12")
return
for effect, var in self.effect_vars.items():
self.effects[effect] = var.get()
self.status_label.config(text="正在初始化...", fg="#f39c12")
self.root.update()
wallpaper_path = r"C:\Users\Administrator\Pictures\bing_wallpapers\bing_wallpaper_20251224_130106.jpg"
try:
self.wallpaper_image = Image.open(wallpaper_path).convert('RGBA')
self.wallpaper_image = self.wallpaper_image.resize((self.screen_width, self.screen_height), Image.Resampling.LANCZOS)
except Exception as e:
self.status_label.config(text=f"加载壁纸失败:{str(e)}", fg="#e74c3c")
return
try:
self.title_font = ImageFont.truetype("C:\\Windows\\Fonts\\msyh.ttc", 80)
self.task_font = ImageFont.truetype("C:\\Windows\\Fonts\\msyh.ttc", 24)
self.date_font = ImageFont.truetype("C:\\Windows\\Fonts\\msyh.ttc", 36)
except:
self.title_font = ImageFont.load_default()
self.task_font = ImageFont.load_default()
self.date_font = ImageFont.load_default()
self.animation_start_time = time.time()
self.last_update_time = 0
self.frame_count = 0
self.fireworks = []
self.last_firework_time = 0
self.is_running = True
self.root.after(100, self.start_animation_loop)
self.status_label.config(text="烟花壁纸已启动", fg="#2ecc71")
def start_animation_loop(self):
"""启动动画循环"""
if self.is_running:
self.animate()
def animate(self):
"""执行动画循环"""
if not self.is_running or not hasattr(self, 'wallpaper_image'):
return
try:
current_time = time.time()
delta_time = current_time - self.last_update_time if hasattr(self, 'last_update_time') else 0.016
if hasattr(self, 'last_update_time') and current_time - self.last_update_time < 0.066:
self.root.after(10, self.animate)
return
self.last_update_time = current_time
self.frame_count += 1
composite_image = self.wallpaper_image.copy()
draw = ImageDraw.Draw(composite_image)
if self.effects['fireworks']:
self.update_fireworks(draw, current_time, delta_time)
if self.effects['tasks_display']:
self.draw_tasks(draw, current_time)
if self.effects['date_display']:
self.draw_date_info(draw, current_time)
temp_wallpaper_path = os.path.join(os.path.dirname(__file__), "temp_wallpaper.bmp")
update_wallpaper = False
if not hasattr(self, 'last_wallpaper_time'):
update_wallpaper = True
elif current_time - self.last_wallpaper_time > 0.3:
update_wallpaper = True
elif self.frame_count % 3 == 0:
update_wallpaper = True
if update_wallpaper:
composite_image.convert('RGB').save(temp_wallpaper_path, 'BMP')
ctypes.windll.user32.SystemParametersInfoW(20, 0, temp_wallpaper_path, 0)
self.last_wallpaper_time = current_time
except Exception as e:
print(f"设置壁纸时出错:{e}")
self.root.after(10, self.animate)
def update_fireworks(self, draw, current_time, delta_time):
"""更新烟花系统"""
if current_time - self.last_firework_time > self.firework_interval:
if random.random() < 0.7:
self.launch_firework()
self.last_firework_time = current_time
alive_fireworks = []
for firework in self.fireworks:
if firework.update(delta_time):
alive_fireworks.append(firework)
firework.draw(draw)
self.fireworks = alive_fireworks
def launch_firework(self):
"""发射新烟花"""
x = random.randint(100, self.screen_width - 100)
y = self.screen_height + 50
color = random.choice(self.firework_colors)
explosion_height = random.randint(100, self.screen_height // 2)
firework = Firework(x, y, color, explosion_height)
self.fireworks.append(firework)
def draw_tasks(self, draw, current_time):
"""绘制任务信息"""
if not self.tasks:
return
start_x = self.screen_width - 400
start_y = 150
title_text = "今日任务"
draw.text((start_x, start_y), title_text, fill=(233, 69, 96, 255), font=self.title_font)
for i, task in enumerate(self.tasks):
y_pos = start_y + 100 + i * 40
status_icon = "✓" if task.completed else "○"
status_color = (149, 165, 166, 255) if task.completed else (233, 69, 96, 255)
draw.text((start_x, y_pos), status_icon, fill=status_color, font=self.task_font)
text_color = (149, 165, 166, 255) if task.completed else (255, 255, 255, 255)
draw.text((start_x + 40, y_pos), task.text, fill=text_color, font=self.task_font)
def draw_date_info(self, draw, current_time):
"""绘制日期信息"""
now = datetime.now()
date_text = now.strftime("%Y年%m月%d日")
week_text = now.strftime("星期%w").replace("星期 0", "星期日")
time_text = now.strftime("%H:%M:%S")
date_bbox = draw.textbbox((0, 0), date_text, font=self.date_font)
week_bbox = draw.textbbox((0, 0), week_text, font=self.date_font)
time_bbox = draw.textbbox((0, 0), time_text, font=self.date_font)
date_width = date_bbox[2] - date_bbox[0]
date_height = date_bbox[3] - date_bbox[1]
week_width = week_bbox[2] - week_bbox[0]
week_height = week_bbox[3] - week_bbox[1]
time_width = time_bbox[2] - time_bbox[0]
time_height = time_bbox[3] - time_bbox[1]
base_x = self.screen_width - max(date_width, week_width, time_width) - 80
time_y = self.screen_height - time_height - 80
week_y = time_y - week_height - 15
date_y = week_y - date_height - 15
draw.text((base_x, date_y), date_text, fill=(233, 69, 96, 255), font=self.date_font)
draw.text((base_x, week_y), week_text, fill=(255, 255, 255, 255), font=self.date_font)
draw.text((base_x, time_y), time_text, fill=(78, 205, 196, 255), font=self.date_font)
def stop_wallpaper(self):
"""停止壁纸"""
self.is_running = False
try:
temp_wallpaper_path = os.path.join(os.path.dirname(__file__), "temp_wallpaper.bmp")
if os.path.exists(temp_wallpaper_path):
os.remove(temp_wallpaper_path)
except:
pass
if hasattr(self, 'wallpaper_image'):
delattr(self, 'wallpaper_image')
self.status_label.config(text="壁纸已停止", fg="#e74c3c")
def on_closing(self):
"""关闭程序"""
self.stop_wallpaper()
self.save_tasks()
self.root.quit()
self.root.destroy()
def main():
"""主函数"""
try:
if not ctypes.windll.shell32.IsUserAnAdmin():
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
sys.exit()
app = FireworkWallpaper()
app.root.mainloop()
except Exception as e:
messagebox.showerror("错误", f"程序运行时发生错误:{str(e)}")
if __name__ == "__main__":
main()