-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMinecraft_clock.py
More file actions
118 lines (95 loc) · 3.98 KB
/
Copy pathMinecraft_clock.py
File metadata and controls
118 lines (95 loc) · 3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import tkinter as tk
from PIL import Image, ImageTk
import datetime
import os
import sys
import ctypes
import win32gui
import win32con
TOTAL_IMAGES = 63
IMAGES_PATH = "frames"
ICON_FILENAME = "icon.ico"
def resource_path(relative_path):
"""Get absolute path to resource, works for dev and PyInstaller"""
base_path = getattr(sys, '_MEIPASS', os.path.abspath("."))
return os.path.join(base_path, relative_path)
def set_win_taskbar_icon(window, icon_path):
"""Force taskbar + Alt+Tab icon (replaces feather) using WinAPI"""
hwnd = ctypes.windll.user32.GetParent(window.winfo_id())
if os.path.exists(icon_path):
hicon = ctypes.windll.user32.LoadImageW(
0, icon_path, 1, 0, 0, 0x00000010 # IMAGE_ICON, LR_LOADFROMFILE
)
if hicon:
ctypes.windll.user32.SendMessageW(hwnd, 0x80, 1, hicon) # small icon
ctypes.windll.user32.SendMessageW(hwnd, 0x80, 0, hicon) # big icon
def minutes_since_noon(hour, minute):
if hour < 12:
hour += 24
return (hour - 12) * 60 + minute
def get_image_index(hour, minute):
minutes = minutes_since_noon(hour, minute)
index = int(minutes // (720 / (TOTAL_IMAGES / 2))) % TOTAL_IMAGES
return index
class MinecraftClockApp(tk.Tk):
def __init__(self):
super().__init__()
# Set a unique AppUserModelID for taskbar
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(u"minecraft.clock.app")
# Configure window
self.geometry("300x300+100+100")
self.title("Minecraft Clock")
self.configure(bg="white")
self.wm_attributes("-transparentcolor", "white")
self.wm_attributes("-topmost", True)
# Set taskbar icon via WinAPI
icon_path = resource_path(ICON_FILENAME)
set_win_taskbar_icon(self, icon_path)
# Remove frame and make it appear in taskbar
self.after(100, self.set_taskbar_window)
# Label to show image
self.label = tk.Label(self, bg="white")
self.label.pack(fill="both", expand=True)
# Enable dragging
self.bind("<ButtonPress-1>", self.start_move)
self.bind("<B1-Motion>", self.do_move)
# Right-click to exit
self.bind("<Button-3>", lambda e: self.destroy())
# Load image and update regularly
self.update_image()
self.after(10000, self.periodic_update)
def set_taskbar_window(self):
hwnd = ctypes.windll.user32.GetParent(self.winfo_id())
style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE)
style &= ~win32con.WS_OVERLAPPEDWINDOW
style |= win32con.WS_POPUP | win32con.WS_VISIBLE
win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, style)
exStyle = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
exStyle |= win32con.WS_EX_APPWINDOW
exStyle &= ~win32con.WS_EX_TOOLWINDOW
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, exStyle)
win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 100, 100, 300, 300,
win32con.SWP_FRAMECHANGED | win32con.SWP_SHOWWINDOW)
def update_image(self):
now = datetime.datetime.now()
idx = get_image_index(now.hour, now.minute)
frame_path = resource_path(os.path.join(IMAGES_PATH, f"frame_{idx}.png"))
if os.path.exists(frame_path):
img = Image.open(frame_path).resize((300, 300), Image.LANCZOS)
self.tk_img = ImageTk.PhotoImage(img)
self.label.configure(image=self.tk_img)
else:
self.label.configure(text=f"Missing frame_{idx}.png", image='', bg='white')
def periodic_update(self):
self.update_image()
self.after(10000, self.periodic_update)
def start_move(self, event):
self._x = event.x
self._y = event.y
def do_move(self, event):
x = self.winfo_pointerx() - self._x
y = self.winfo_pointery() - self._y
self.geometry(f"+{x}+{y}")
if __name__ == "__main__":
app = MinecraftClockApp()
app.mainloop()