1
0
Files
Programm-Shortcut/utils/icon_utils.py
2025-09-08 17:19:22 +02:00

94 lines
3.3 KiB
Python

import sys
import os
from typing import Optional, Dict, Any
try:
import win32ui
import win32gui
import win32con
import win32api
from PIL import Image, ImageTk
ICON_SUPPORT = True
except ImportError:
print("Warnung: Die Bibliotheken für Programm-Icons fehlen. Installieren Sie diese mit: pip install pywin32 Pillow")
ICON_SUPPORT = False
class IconManager:
def __init__(self):
self.icon_cache: Dict[str, Any] = {}
self.icon_support = ICON_SUPPORT
def resource_path(self, relative_path: str) -> str:
"""Get absolute path to resource, works for dev and for PyInstaller"""
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
def extract_icon_from_exe(self, exe_path: str) -> Optional[Any]:
"""Extrahiert das Icon aus einer EXE-Datei"""
if not self.icon_support:
return None
try:
# Icon-Handle erhalten
large, small = win32gui.ExtractIconEx(exe_path, 0)
# Wir verwenden das größere Icon
if large:
# Wir nehmen das erste Icon
ico_x = win32api.GetSystemMetrics(win32con.SM_CXICON)
ico_y = win32api.GetSystemMetrics(win32con.SM_CYICON)
# Icon in DC (Device Context) zeichnen
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, ico_x, ico_y)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)
hdc.DrawIcon((0, 0), large[0])
# Bitmap in ein Python-Image-Objekt umwandeln
bmpinfo = hbmp.GetInfo()
bmpstr = hbmp.GetBitmapBits(True)
img = Image.frombuffer(
'RGBA',
(bmpinfo['bmWidth'], bmpinfo['bmHeight']),
bmpstr, 'raw', 'BGRA', 0, 1
)
# Aufräumen
win32gui.DestroyIcon(large[0])
for icon in small:
if icon:
win32gui.DestroyIcon(icon)
# Bild auf die gewünschte Größe skalieren
img = img.resize((16, 16), Image.LANCZOS)
# In PhotoImage umwandeln für Tkinter
return ImageTk.PhotoImage(img)
return None
except Exception as e:
print(f"Fehler beim Extrahieren des Icons: {str(e)}")
return None
def get_icon(self, program_path: str) -> Optional[Any]:
"""Holt ein Icon aus dem Cache oder extrahiert es neu"""
if not self.icon_support:
return None
if program_path in self.icon_cache:
return self.icon_cache[program_path]
icon = self.extract_icon_from_exe(program_path)
self.icon_cache[program_path] = icon
return icon
def clear_cache(self):
"""Leert den Icon-Cache"""
self.icon_cache.clear()