mirror of
https://github.com/Andre-Bzk/FocusFix.git
synced 2026-11-15 09:33:14 +01:00
406 lines
18 KiB
Markdown
406 lines
18 KiB
Markdown
# Game Foreground Fix
|
||
|
||
Windows-Hilfsprogramm, das ein Spielfenster automatisch in den Vordergrund bringt. Gedacht für Spiele wie Crimson Desert, die nach dem Start im Hintergrund landen oder von Steam, Taskleiste, Splashscreens oder Overlay-Fenstern verdeckt werden. Funktioniert mit **Steam** (automatische Prozesserkennung) und **Sunshine/Moonlight** (manueller Prozessname).
|
||
|
||
---
|
||
|
||
## Inhaltsverzeichnis
|
||
|
||
- [Problembeschreibung](#problembeschreibung)
|
||
- [Lösungsansatz](#lösungsansatz)
|
||
- [Architektur](#architektur)
|
||
- [Voraussetzungen](#voraussetzungen)
|
||
- [Installation](#installation)
|
||
- [Konfiguration](#konfiguration)
|
||
- [Steam](#steam)
|
||
- [Sunshine / Moonlight](#sunshine--moonlight)
|
||
- [Ablauf zur Laufzeit](#ablauf-zur-laufzeit)
|
||
- [Dateireferenz](#dateireferenz)
|
||
- [launch.vbs](#launchvbs)
|
||
- [foreground_fix.py](#foreground_fixpy)
|
||
- [Konfigurationsparameter](#konfigurationsparameter)
|
||
- [Windows API — Technischer Hintergrund](#windows-api--technischer-hintergrund)
|
||
- [Das SetForegroundWindow-Problem](#das-setforegroundwindow-problem)
|
||
- [Workaround-Strategie](#workaround-strategie)
|
||
- [Splashscreen-Erkennung](#splashscreen-erkennung)
|
||
- [Manuelles Testen](#manuelles-testen)
|
||
- [Debugging](#debugging)
|
||
- [Bekannte Einschränkungen](#bekannte-einschränkungen)
|
||
|
||
---
|
||
|
||
## Problembeschreibung
|
||
|
||
Beim Start eines Spiels über Steam oder Sunshine/Moonlight öffnet sich das Spielfenster im **Hintergrund** — die Steam-Oberfläche, die Windows-Taskleiste oder andere Fenster verdecken es. Der Spieler muss manuell per Alt+Tab zum Spiel wechseln.
|
||
|
||
Ursache: Windows vergibt den Vordergrundfokus an den Prozess, der ihn aktuell besitzt. Das Spielfenster erhält keinen automatischen Fokus, weil es von einem anderen Prozess (Steam-Launcher, Sunshine) erzeugt wurde.
|
||
|
||
Zusätzlich erzeugen manche Spiele beim Start mehrere Fenster — Splashscreens, Launcher oder titellose Overlay-Fenster — die den Fokus stören können.
|
||
|
||
## Lösungsansatz
|
||
|
||
Ein Python-Script überwacht den Spielstart, wartet auf das Hauptfenster des Spiels und erzwingt den Vordergrundfokus über Windows-API-Aufrufe. Ein VBScript-Wrapper sorgt bei Steam dafür, dass weder ein Konsolenfenster noch andere störende Fenster erscheinen. Das Tool ist nicht auf ein bestimmtes Spiel festgelegt, sondern auf typische Startprobleme mit ähnlichem Fensterverhalten ausgelegt.
|
||
|
||
## Architektur
|
||
|
||
```
|
||
Steam Launch Options / Sunshine Befehlsvorbereitung
|
||
│
|
||
▼
|
||
┌──────────┐ extrahiert Prozessname ┌────────────────────┐
|
||
│ launch.vbs├──── aus %command% ────────────►│ pythonw.exe │
|
||
│ (nur Steam)│ + startet unsichtbar │ foreground_fix.py │
|
||
│ │ │ --process GameName │
|
||
│ │ startet normal │ │
|
||
│ ├────────────────────────────────►│ (wartet auf Spiel) │
|
||
└──────────┘ %command% = Spiel.exe └────────┬───────────┘
|
||
│
|
||
Fenster gefunden
|
||
│
|
||
┌────────▼───────────┐
|
||
│ 1. Fenster erkennen│
|
||
│ 2. Größe abwarten │
|
||
│ 3. Spiel fokussieren│
|
||
│ 4. Wechsel beobachten│
|
||
│ 5. Script beendet │
|
||
└────────────────────┘
|
||
```
|
||
|
||
**Zwei Dateien**, klare Aufgabentrennung:
|
||
|
||
| Datei | Sprache | Aufgabe |
|
||
|---|---|---|
|
||
| `launch.vbs` | VBScript | Startrampe (nur Steam): extrahiert Prozessname aus `%command%`, startet das Python-Script unsichtbar und leitet den Spielstart weiter |
|
||
| `foreground_fix.py` | Python 3 | Kernlogik: Prozess-Monitoring, Fenstererkennung, Fensterwechsel-Erkennung, Fokus-Erzwingung, Logging |
|
||
|
||
## Voraussetzungen
|
||
|
||
| Komponente | Version | Hinweis |
|
||
|---|---|---|
|
||
| Windows | 10 / 11 | Benötigt Win32 API (user32.dll) |
|
||
| Python | 3.10+ | `py` Launcher muss verfügbar sein |
|
||
| pip-Pakete | `psutil`, `pywin32` | Werden im `.venv` installiert |
|
||
| Steam | Beliebig | Startoptionen müssen konfigurierbar sein |
|
||
|
||
## Installation
|
||
|
||
```bash
|
||
cd C:\Projekte\Steam_backgroud_fix
|
||
|
||
# Virtual Environment erstellen
|
||
py -m venv .venv
|
||
|
||
# Aktivieren
|
||
.venv\Scripts\activate
|
||
|
||
# Abhängigkeiten installieren
|
||
pip install psutil pywin32
|
||
```
|
||
|
||
### Dateistruktur nach Installation
|
||
|
||
```
|
||
C:\Projekte\Steam_backgroud_fix\
|
||
├── .venv\ # Python Virtual Environment
|
||
├── foreground_fix.py # Hauptscript (Kernlogik)
|
||
├── foreground_fix.log # Logdatei (wird automatisch erstellt)
|
||
├── launch.vbs # VBScript-Wrapper für Steam
|
||
├── CLAUDE.md # Kontext für Claude Code
|
||
└── README.md # Diese Dokumentation
|
||
```
|
||
|
||
## Konfiguration
|
||
|
||
### Steam
|
||
|
||
1. Steam öffnen → **Bibliothek**
|
||
2. Rechtsklick auf das Spiel → **Eigenschaften**
|
||
3. Unter **Allgemein → Startoptionen** eintragen:
|
||
|
||
```
|
||
wscript "C:\Projekte\Steam_backgroud_fix\launch.vbs" %command%
|
||
```
|
||
|
||
`launch.vbs` extrahiert den Prozessnamen automatisch aus `%command%` — **keine manuelle Anpassung pro Spiel nötig**. Die gleiche Startoption kann für beliebige Steam-Spiele mit vergleichbarem Fokus-Problem verwendet werden.
|
||
|
||
**Erklärung:**
|
||
- `wscript` — Windows Script Host, führt VBScript ohne Konsolenfenster aus
|
||
- `"...\launch.vbs"` — Pfad zum VBScript-Wrapper
|
||
- `%command%` — Steam-Platzhalter, wird zur Laufzeit durch den vollständigen Pfad zur Spiel-Executable ersetzt (z.B. `"C:\SteamLibrary\...\Game.exe"`)
|
||
|
||
### Sunshine / Moonlight
|
||
|
||
In Sunshine als **Befehlsvorbereitung** (Command Preparation) pro Spiel eintragen:
|
||
|
||
```
|
||
"C:\Projekte\Steam_backgroud_fix\.venv\Scripts\pythonw.exe" "C:\Projekte\Steam_backgroud_fix\foreground_fix.py" --process "Prozessname"
|
||
```
|
||
|
||
Den Prozessnamen im Task-Manager ablesen (ohne `.exe`). Beispiele:
|
||
|
||
| Spiel | Prozessname |
|
||
|---|---|
|
||
| Crimson Desert | `CrimsonDesert` |
|
||
| Wuthering Waves | `Client-Win64-Shipping` |
|
||
|
||
**Wichtig:** Der vollständige Pfad zu `pythonw.exe` im `.venv` ist nötig, damit die Abhängigkeiten (`psutil`, `pywin32`) gefunden werden. `py` oder `python` nutzt die globale Python-Installation ohne diese Pakete.
|
||
|
||
## Ablauf zur Laufzeit
|
||
|
||
```
|
||
Zeitachse
|
||
─────────────────────────────────────────────────────────────────────
|
||
t=0s Steam/Sunshine startet das Script mit --process "GameName"
|
||
t=0.1s foreground_fix.py beginnt zu pollen (alle 0.5s)
|
||
→ Sucht nach Prozess "GameName"
|
||
|
||
t=~3s Spielprozess gestartet, ggf. Splashscreen erscheint
|
||
→ Script findet den Prozess (PID)
|
||
→ Sucht nach Fenster mit Breite >= 800px
|
||
→ Splashscreen ist kleiner → wird ignoriert
|
||
|
||
t=~10s Hauptfenster des Spiels erscheint (z.B. 2560×1440)
|
||
→ Script findet das Fenster (bevorzugt Fenster mit Titel)
|
||
→ Wartet 3 Sekunden (Initialisierung abwarten)
|
||
→ Wartet bis Fenstergröße stabil ist
|
||
|
||
t=~13s Phase 3: Fokus-Erzwingung
|
||
→ Spielfenster wird in den Vordergrund gebracht
|
||
→ Bei Misserfolg: bis zu 15 Wiederholungen (je 2s Pause)
|
||
→ Beobachtet ob sich das Fenster ändert (Splash → Hauptfenster)
|
||
→ Ignoriert titellose Overlay-Fenster
|
||
|
||
t=~15s Erfolg → foreground_fix.py beendet sich
|
||
→ Logdatei enthält den vollständigen Ablauf
|
||
```
|
||
|
||
## Dateireferenz
|
||
|
||
### launch.vbs
|
||
|
||
```vb
|
||
Set WshShell = CreateObject("WScript.Shell")
|
||
|
||
' Prozessname aus dem ersten Argument (Steam %command%) extrahieren
|
||
Dim exePath, fso, exeName
|
||
Set fso = CreateObject("Scripting.FileSystemObject")
|
||
exePath = WScript.Arguments(0)
|
||
exeName = fso.GetBaseName(exePath)
|
||
|
||
' Foreground-Fix unsichtbar starten mit extrahiertem Prozessnamen
|
||
WshShell.Run """...\pythonw.exe"" ""...\foreground_fix.py"" --process """ & exeName & """", 0, False
|
||
|
||
' Spiel starten: Steam-Argumente zusammensetzen
|
||
Dim gameCmd, i
|
||
gameCmd = ""
|
||
For i = 0 To WScript.Arguments.Count - 1
|
||
gameCmd = gameCmd & """" & WScript.Arguments(i) & """ "
|
||
Next
|
||
If gameCmd <> "" Then
|
||
WshShell.Run gameCmd, 1, False
|
||
End If
|
||
```
|
||
|
||
**`WshShell.Run` Parameter:**
|
||
|
||
| Parameter | Wert | Bedeutung |
|
||
|---|---|---|
|
||
| Command | `"pythonw.exe" "foreground_fix.py" --process "GameName"` | Auszuführender Befehl |
|
||
| WindowStyle | `0` | Fenster komplett versteckt |
|
||
| WaitOnReturn | `False` | Nicht auf Beendigung warten (asynchron) |
|
||
|
||
**Warum `pythonw.exe` statt `python.exe`?**
|
||
`python.exe` ist eine Konsolenanwendung und erzeugt automatisch ein CMD-Fenster. `pythonw.exe` ist die "windowless"-Variante — identischer Python-Interpreter, aber ohne Konsole.
|
||
|
||
**Warum VBScript statt Batch?**
|
||
Eine `.bat`-Datei wird von `cmd.exe` ausgeführt, das immer ein Konsolenfenster öffnet — selbst wenn es sich sofort wieder schließt. VBScript über `wscript.exe` erzeugt zu keinem Zeitpunkt ein sichtbares Fenster.
|
||
|
||
### foreground_fix.py
|
||
|
||
#### Funktionsübersicht
|
||
|
||
| Funktion | Beschreibung |
|
||
|---|---|
|
||
| `find_process_pids(name)` | Sucht laufende Prozesse nach Name (Teilstring, case-insensitiv), gibt PIDs zurück |
|
||
| `find_game_window(pids)` | Findet das Hauptfenster der gegebenen PIDs — bevorzugt Fenster mit Titel, dann nach Größe |
|
||
| `wait_for_stable_size(hwnd)` | Wartet bis die Fenstergröße sich stabilisiert hat (kein Resize mehr) |
|
||
| `is_foreground(hwnd)` | Prüft ob ein Fenster aktuell im Vordergrund ist |
|
||
| `bring_to_front(hwnd)` | Erzwingt den Vordergrundfokus für ein Fenster (Alt-Key + AttachThreadInput) |
|
||
| `main()` | Orchestriert den 3-Phasen-Ablauf |
|
||
|
||
#### `find_game_window(pids)` — Fensterauswahl
|
||
|
||
Nutzt `win32gui.EnumWindows()` um alle Top-Level-Fenster zu durchlaufen. Für jedes Fenster:
|
||
|
||
1. Prüft Sichtbarkeit (`IsWindowVisible`)
|
||
2. Ermittelt die zugehörige PID (`GetWindowThreadProcessId`)
|
||
3. Misst die Fenstergröße (`GetWindowRect`)
|
||
4. Filtert nach `MIN_WINDOW_WIDTH` (Standard: 800px)
|
||
|
||
Bei mehreren Treffern wird das Fenster **mit Titel bevorzugt**, dann nach Fläche sortiert. Dadurch werden sowohl Splashscreens (zu klein) als auch titellose Overlay-Fenster (kein Titel) vom Hauptfenster unterschieden.
|
||
|
||
#### `bring_to_front(hwnd)` — Fokus-Erzwingung
|
||
|
||
Erzwingt den Vordergrundfokus trotz Windows-Einschränkungen:
|
||
|
||
```python
|
||
try:
|
||
# Schritt 1: Alt-Taste simulieren (hebt SetForegroundWindow-Sperre auf)
|
||
keybd_event(VK_MENU, 0, 0, 0)
|
||
|
||
# Schritt 2: Thread-Input verbinden
|
||
AttachThreadInput(target_thread, foreground_thread, True)
|
||
|
||
# Schritt 3: Fenster anzeigen und fokussieren
|
||
ShowWindow(hwnd, SW_SHOW)
|
||
BringWindowToTop(hwnd)
|
||
SetForegroundWindow(hwnd)
|
||
SetFocus(hwnd)
|
||
SetActiveWindow(hwnd)
|
||
|
||
# Schritt 4: Thread-Input trennen
|
||
AttachThreadInput(target_thread, foreground_thread, False)
|
||
except Exception:
|
||
...
|
||
finally:
|
||
# Alt-Taste wird IMMER losgelassen, auch bei Fehlern
|
||
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0)
|
||
```
|
||
|
||
Die Alt-Taste wird in einem `finally`-Block freigegeben, damit sie bei Fehlern (z.B. ungültiges Handle, fehlende Rechte) nicht systemweit gedrückt bleibt.
|
||
|
||
#### `main()` — Dreistufiger Ablauf
|
||
|
||
1. **Phase 1 — Prozess-Suche:** Pollt alle 0,5 Sekunden nach dem Prozessnamen. Bricht nach `--timeout` Sekunden ab.
|
||
|
||
2. **Phase 2 — Fenster-Suche:** Pollt alle 0,5 Sekunden nach einem sichtbaren Fenster mit ausreichender Größe. Nach Fund: 3 Sekunden Wartezeit für die vollständige Initialisierung.
|
||
|
||
3. **Phase 3 — Fokus mit Fensterwechsel-Erkennung:** Bis zu 15 Versuche den Spielfokus zu erzwingen, mit je 2 Sekunden Pause. Beobachtet dabei, ob sich das Fenster ändert (z.B. Splash → Hauptfenster) und fokussiert das neue Fenster. Titellose Overlay-Fenster werden ignoriert, wenn bereits ein Fenster mit Titel fokussiert wurde.
|
||
|
||
## Konfigurationsparameter
|
||
|
||
### Kommandozeilenargumente
|
||
|
||
| Argument | Pflicht | Standard | Beschreibung |
|
||
|---|---|---|---|
|
||
| `--process` | Ja | — | Teilstring des Prozessnamens (case-insensitiv, ohne `.exe`) |
|
||
| `--timeout` | Nein | `120` | Maximale Wartezeit in Sekunden für Prozess- und Fensterfund |
|
||
|
||
### Konstanten in `foreground_fix.py`
|
||
|
||
| Konstante | Wert | Beschreibung |
|
||
|---|---|---|
|
||
| `MIN_WINDOW_WIDTH` | `800` | Mindestbreite in Pixeln, um Splashscreens auszufiltern |
|
||
| `FOCUS_RETRIES` | `15` | Maximale Anzahl der Fokus-Versuche |
|
||
| `FOCUS_RETRY_DELAY` | `2.0` | Sekunden zwischen Fokus-Versuchen |
|
||
|
||
### Hardcodierte Pfade in `launch.vbs`
|
||
|
||
| Pfad | Zweck |
|
||
|---|---|
|
||
| `C:\Projekte\Steam_backgroud_fix\.venv\Scripts\pythonw.exe` | Python-Interpreter (windowless) |
|
||
| `C:\Projekte\Steam_backgroud_fix\foreground_fix.py` | Hauptscript |
|
||
|
||
Bei einer Änderung des Installationsverzeichnisses müssen diese Pfade in `launch.vbs` angepasst werden.
|
||
|
||
## Windows API — Technischer Hintergrund
|
||
|
||
### Das SetForegroundWindow-Problem
|
||
|
||
Seit Windows 2000 verhindert das Betriebssystem, dass beliebige Prozesse den Vordergrundfokus "stehlen" können. `SetForegroundWindow(hwnd)` funktioniert nur, wenn:
|
||
|
||
- Der aufrufende Prozess der Vordergrundprozess ist, **oder**
|
||
- Der aufrufende Prozess von dem Vordergrundprozess gestartet wurde, **oder**
|
||
- Der letzte Eingabe-Event vom aufrufenden Prozess stammt
|
||
|
||
Andernfalls blinkt das Fenster lediglich in der Taskleiste.
|
||
|
||
Da `foreground_fix.py` als eigenständiger Prozess läuft (nicht vom Spiel gestartet), erfüllt es keine dieser Bedingungen.
|
||
|
||
### Workaround-Strategie
|
||
|
||
Das Script kombiniert drei Techniken:
|
||
|
||
**1. Alt-Key-Simulation (`keybd_event`)**
|
||
|
||
Simuliert einen Tastendruck der Alt-Taste. Windows behandelt den aufrufenden Prozess danach so, als hätte der Benutzer eine Eingabe getätigt — dies hebt die `SetForegroundWindow`-Sperre auf.
|
||
|
||
**2. Thread-Input-Verbindung (`AttachThreadInput`)**
|
||
|
||
Verbindet die Eingabewarteschlangen zweier Threads. Danach teilen sich beide Threads den gleichen Eingabefokus-Zustand. Der Ziel-Thread (Spiel) kann nun den Fokus erhalten, als wäre er Teil des Vordergrund-Threads.
|
||
|
||
**3. Mehrfache Fokus-Befehle**
|
||
|
||
`ShowWindow`, `BringWindowToTop`, `SetForegroundWindow`, `SetFocus` und `SetActiveWindow` adressieren jeweils einen leicht anderen Aspekt des Fenster-Fokus unter Windows. Die Kombination stellt sicher, dass das Fenster sowohl visuell im Vordergrund ist als auch Tastatur- und Mauseingaben empfängt.
|
||
|
||
### Splashscreen-Erkennung
|
||
|
||
Viele Spiele zeigen beim Start einen Splashscreen, bevor das Hauptfenster erscheint. Beide gehören zum selben Prozess.
|
||
|
||
**Unterscheidungsmerkmal: Fenstergröße.** Der Splashscreen ist typischerweise 300–600px breit. Das Spielfenster ist mindestens so groß wie die Bildschirmauflösung (z.B. 2560×1440). Der Schwellwert `MIN_WINDOW_WIDTH = 800` trennt beide zuverlässig.
|
||
|
||
Zusätzlich erzeugen manche Spiele (z.B. Wuthering Waves) **titellose Overlay-Fenster** in voller Bildschirmgröße. Diese werden durch die Bevorzugung von Fenstern mit Titel in der Sortierung und durch die Fensterwechsel-Logik ignoriert.
|
||
|
||
## Manuelles Testen
|
||
|
||
### Script alleine testen (Spiel muss laufen)
|
||
|
||
```bash
|
||
cd C:\Projekte\Steam_backgroud_fix
|
||
.venv\Scripts\python foreground_fix.py --process "CrimsonDesert" --timeout 5
|
||
```
|
||
|
||
Die Laufzeit-Logs landen in `foreground_fix.log`. Bei Ausführung über `pythonw.exe` gibt es keine sichtbare Ausgabe; bei manuellen Starts mit `python.exe` können Argument- oder Interpreter-Fehler weiterhin in der Konsole erscheinen.
|
||
|
||
### VBScript alleine testen
|
||
|
||
```bash
|
||
wscript "C:\Projekte\Steam_backgroud_fix\launch.vbs" "C:\dummy\TestGame.exe"
|
||
```
|
||
|
||
Sollte das Python-Script unsichtbar starten mit `--process "TestGame"`. Prüfen ob `pythonw.exe` im Task-Manager erscheint.
|
||
|
||
### Gesamtablauf testen
|
||
|
||
1. Steam-Startoptionen wie oben konfigurieren
|
||
2. Spiel über Steam starten
|
||
3. Erwartung: Spielfenster erscheint nach dem Ladescreen im Vordergrund, keine Taskleiste sichtbar, keine CMD- oder Script-Fenster
|
||
4. `foreground_fix.log` prüfen für den detaillierten Ablauf
|
||
|
||
## Debugging
|
||
|
||
Alle Informationen werden in `foreground_fix.log` protokolliert:
|
||
|
||
- Gefundene Kandidaten-Fenster (Handle, Titel, Größe, PID)
|
||
- Fensterwechsel und ignorierte titellose Fenster
|
||
- Fokus-Versuche mit Ergebnis (Erfolg/Misserfolg)
|
||
- Fehler mit vollständigem Traceback
|
||
|
||
### Häufige Probleme
|
||
|
||
| Symptom | Ursache | Lösung |
|
||
|---|---|---|
|
||
| Spiel startet nicht | Steam-Startoptionen fehlerhaft | Prüfen ob `%command%` am Ende steht |
|
||
| `ModuleNotFoundError: psutil` | Globales Python statt venv | Vollständigen Pfad zu `.venv\Scripts\pythonw.exe` verwenden |
|
||
| Script findet Prozess nicht | Prozessname stimmt nicht | `--process` anpassen, Namen im Task-Manager prüfen |
|
||
| Fenster wird nicht fokussiert | Windows-Restriktion zu streng | Retry-Anzahl/Delay in Konstanten erhöhen |
|
||
| Alt-Taste bleibt hängen | Spiel mit Admin-Rechten, Script ohne | Script ebenfalls als Admin starten |
|
||
| CMD-Fenster sichtbar | `python.exe` statt `pythonw.exe` | Pfad in `launch.vbs` bzw. Sunshine-Konfiguration prüfen |
|
||
| Verdunkeltes/blockiertes Spiel | Titelloses Overlay-Fenster | Log prüfen — sollte durch Fenster-mit-Titel-Bevorzugung gelöst sein |
|
||
|
||
### Fenster-Inspektion per PowerShell
|
||
|
||
Um alle Fenster eines laufenden Spielprozesses zu inspizieren:
|
||
|
||
```powershell
|
||
Get-Process -Name GameName | Select-Object Id, Name, MainWindowTitle, MainWindowHandle
|
||
```
|
||
|
||
## Bekannte Einschränkungen
|
||
|
||
- **Kein Admin erforderlich**, aber manche Spiele starten mit erhöhten Rechten — in dem Fall muss das Script ebenfalls als Admin laufen
|
||
- **Exklusiver Vollbildmodus:** Spiele im exklusiven Vollbild (kein Borderless Windowed) können sich anders verhalten, da sie die komplette Bildschirmausgabe übernehmen
|
||
- **Anti-Cheat:** Einige Anti-Cheat-Systeme könnten die `keybd_event`-Simulation oder `AttachThreadInput`-Aufrufe als verdächtig einstufen — bisher keine Probleme bekannt
|
||
- **Mehrere Monitore:** `find_game_window` wählt das Fenster unabhängig davon, auf welchem Monitor es liegt
|
||
- **Nicht universell für jedes Spiel:** Das Tool ist generisch für viele ähnliche Fälle, aber nicht garantiert für jeden Launcher, jedes Anti-Cheat-System oder jedes ungewöhnliche Fenster-/Startverhalten
|