Kompletter Rewrite
This commit is contained in:
0
utils/__init__.py
Normal file
0
utils/__init__.py
Normal file
94
utils/icon_utils.py
Normal file
94
utils/icon_utils.py
Normal file
@@ -0,0 +1,94 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user