94 lines
3.3 KiB
Python
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() |