diff --git a/Installer.iss b/Installer.iss index 86f6ce7..f4e7025 100644 --- a/Installer.iss +++ b/Installer.iss @@ -68,8 +68,11 @@ AppComments=Erprobungsfassung. Benutzung auf eigene Gefahr. Name: "deutsch"; MessagesFile: "compiler:Languages\German.isl" [Tasks] +; Kein "unchecked": der Haken ist vorgesetzt. Er hatte nach dem +; Installieren kein Symbol auf dem Desktop und musste das Programm +; suchen (07.09.2026). Wer es nicht will, nimmt den Haken heraus. Name: "desktopicon"; Description: "Verknüpfung auf dem Desktop anlegen"; \ - GroupDescription: "Zusätzliche Verknüpfungen:"; Flags: unchecked + GroupDescription: "Zusätzliche Verknüpfungen:" [Files] ; Der Updater - das ist, was der Benutzer startet. @@ -80,9 +83,11 @@ Source: "dist\{#ExeProgramm}"; DestDir: "{app}"; Flags: ignoreversion [Icons] ; Beide Verknuepfungen zeigen auf den UPDATER, nicht auf das Programm. -Name: "{group}\{#Name}"; Filename: "{app}\{#ExeUpdater}" +; IconFilename ausdruecklich: ohne das erbt die Verknuepfung das Symbol vom +; UPDATER, und Windows zeigte an ihrer Stelle das nackte Standardsymbol. +Name: "{group}\{#Name}"; Filename: "{app}\{#ExeUpdater}"; IconFilename: "{app}\{#ExeProgramm}" Name: "{group}\{#Name} deinstallieren"; Filename: "{uninstallexe}" -Name: "{userdesktop}\{#Name}"; Filename: "{app}\{#ExeUpdater}"; Tasks: desktopicon +Name: "{userdesktop}\{#Name}"; Filename: "{app}\{#ExeUpdater}"; IconFilename: "{app}\{#ExeProgramm}"; Tasks: desktopicon [Run] Filename: "{app}\{#ExeUpdater}"; Description: "{#Name} jetzt starten"; \ diff --git a/app.py b/app.py index b2f9dcf..e2c9186 100644 --- a/app.py +++ b/app.py @@ -89,7 +89,8 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin, # dem zweiten Monitor, wenn einer da ist) - sichtbar, aber nicht im # Weg. Unsichtbar machen waere falsch: dann sieht niemand mehr, was # der Pruefstand eigentlich tut. - self.geometry(f"+{self.winfo_screenwidth() + 20}+40") + self.geometry(theme.pruefplatz() + or f"+{self.winfo_screenwidth() + 20}+40") try: # Kein Eintrag in der Taskleiste: das Fenster liegt neben # dem Bildschirm, und ein Eintrag, den man anklickt, ohne diff --git a/theme.py b/theme.py index 6da642c..25502ef 100644 --- a/theme.py +++ b/theme.py @@ -66,6 +66,61 @@ def titelleiste_faerben(fenster, dunkel): return False +def pruefplatz(): + """Wo ein Pruefstand seine Fenster aufmachen soll: "+x+y" oder "". + + Seine Ansage am 07.09.2026: *"teste links auf dem 1080p monitor nicht mehr + auf dem main ... weil da schau ich nun video"*. + + Vorher lag der Platz bei `Bildschirmbreite + 20` - also RECHTS neben dem + Hauptmonitor. Bei ihm steht der zweite Monitor aber LINKS (x = -1920), und + rechts ist gar nichts: die Fenster gingen ins Leere. Sie liefen zwar, waren + aber nirgends zu sehen - das hat beim Bildermachen einige Zeit gekostet. + + Gesucht wird deshalb der nicht-primaere Monitor. Gibt es keinen, bleibt es + beim alten Verhalten (neben den Bildschirm), denn im Weg sein soll ein + Pruefstand auch dann nicht. + """ + if not sys.platform.startswith("win"): + return "" + try: + import ctypes + from ctypes import wintypes + + class RECT(ctypes.Structure): + _fields_ = [("left", ctypes.c_long), ("top", ctypes.c_long), + ("right", ctypes.c_long), ("bottom", ctypes.c_long)] + + class MONITORINFO(ctypes.Structure): + _fields_ = [("cbSize", wintypes.DWORD), ("rcMonitor", RECT), + ("rcWork", RECT), ("dwFlags", wintypes.DWORD)] + + gefunden = [] + + def je_monitor(hmon, hdc, lprect, daten): + info = MONITORINFO() + info.cbSize = ctypes.sizeof(MONITORINFO) + if ctypes.windll.user32.GetMonitorInfoW(hmon, ctypes.byref(info)): + r = info.rcWork + gefunden.append((bool(info.dwFlags & 1), # 1 = MONITORINFOF_PRIMARY + r.left, r.top, r.right - r.left)) + return 1 + + RUECKRUF = ctypes.WINFUNCTYPE(ctypes.c_int, wintypes.HMONITOR, + wintypes.HDC, ctypes.POINTER(RECT), + wintypes.LPARAM) + ctypes.windll.user32.EnumDisplayMonitors(0, 0, RUECKRUF(je_monitor), 0) + # Der breiteste Nebenmonitor - bei mehreren der linkeste. + neben = sorted((m for m in gefunden if not m[0]), + key=lambda m: (-m[3], m[1])) + if neben: + _, x, y, _ = neben[0] + return f"+{x + 30}+{y + 40}" + except Exception: # noqa: BLE001 - dann eben der alte Weg + pass + return "" + + def testlauf(): """Faehrt gerade ein Pruefstand das Programm? @@ -478,10 +533,10 @@ class ThemeMixin: """ d.configure(bg=self.col_bg) if testlauf(): - # Wie das Hauptfenster: neben den Bildschirm, und ohne grab_set - + # Wie das Hauptfenster: auf den zweiten Monitor, und ohne grab_set - # ein Dialog, der Maus und Tastatur festhaelt, blockiert den - # Menschen, der nebenher schreibt. - d.geometry(f"+{d.winfo_screenwidth() + 20}+40") + # Menschen, der nebenher arbeitet. + d.geometry(pruefplatz() or f"+{d.winfo_screenwidth() + 20}+40") d.grab_set = lambda *a, **k: None try: d.attributes("-toolwindow", True) # nicht in die Taskleiste