DPI-Skalierung & Bildschirmkoordinaten: Warum Ihre Klicks an der falschen Stelle landen
Ihre Anzeigeeinstellungen — automatisch erkannt:
Sie haben ein Skript geschrieben, das auf (960, 540) klickt — auf Ihrem alten 1080p-Monitor hat das prima funktioniert. Dann haben Sie auf 4K aufgerüstet, Windows die Skalierung auf 150 % gesetzt, und plötzlich landet derselbe Klick 480 Pixel neben dem Ziel. Ihr Code hat sich nicht geändert. Das Koordinatensystem darunter schon.
DPI-Skalierung ist der häufigste Grund, warum Bildschirmkoordinaten nach einem Monitor-Upgrade, einem neuen Laptop oder dem Verschieben eines Fensters zwischen Displays mit unterschiedlicher Skalierung „kaputtgehen". Nachfolgend erläutern wir, was bei 100 %, 125 %, 150 % und 200 % tatsächlich passiert — und wie Sie es in Ihren Skripten beheben.
Kostenloses Bildschirmkoordinaten-Tool öffnenIhre aktuelle DPI-Skalierung — Live
Ihr Browser meldet Folgendes über Ihr Display im Moment:
Wenn die Device Pixel Ratio 1,0 anzeigt, sind Sie bei 100 % Skalierung — logische und physische Pixel sind identisch. Steht dort 1,5, laufen Sie mit 150 % Skalierung, und es findet eine unsichtbare Koordinatentransformation statt. Nutzen Sie unser Bildschirmkoordinaten-Tool, um zu sehen, wie sich Ihre logische und physische Position in Echtzeit unterscheiden.
Was ist DPI-Skalierung (und warum gibt es sie)?
Ein 27-Zoll-4K-Monitor packt 3840×2160 Pixel in ungefähr denselben physischen Raum wie ein 1080p-Bildschirm. Ohne Skalierung sind Text und Icons winzig — etwa 140 PPI gegenüber ~92 PPI auf einem 24-Zoll-1080p. Nutzbar, aber auf Dauer anstrengend für die Augen.
Deshalb wendet Windows DPI-Skalierung an. Stellen Sie 150 % auf dem 4K-Monitor ein, und Windows tut so, als sei der Bildschirm nur 2560×1440 groß. Es zeichnet alles in dieser kleineren Größe und streckt es dann auf die vollen 3840×2160. Das Ergebnis: Die UI-Elemente haben eine komfortable Größe, werden aber schärfer dargestellt, weil jeder „logische" Pixel auf 1,5 × 1,5 = 2,25 physische Pixel abgebildet wird.
Das Problem: Die meiste Software (und die meisten Automatisierungstools) sieht nur den logischen Koordinatenraum. Sie glauben, der Bildschirm sei 2560×1440, obwohl er in Wirklichkeit 3840×2160 ist. Das führt zu einer Diskrepanz zwischen der Stelle, an der Sie glauben zu klicken, und der Stelle, an der der Klick tatsächlich registriert wird.
Eine tiefere Erklärung, was „physische" und „logische" Pixel tatsächlich sind und wie sie mit CSS-Pixeln, Gerätepixeln und geräteunabhängigen Pixeln zusammenhängen, finden Sie in unserem Leitfaden „Physische vs. logische Pixel".
Logische vs. physische Auflösung bei jedem Skalierungsfaktor
Nachschlagetabelle — suchen Sie Ihre physische Auflösung auf der linken Seite und lesen Sie ab, was Windows Anwendungen bei jedem Skalierungsfaktor tatsächlich meldet:
| Physische Auflösung | 100 % (Logisch) | 125 % (Logisch) | 150 % (Logisch) | 200 % (Logisch) |
|---|---|---|---|---|
| 1920×1080 | 1920×1080 | 1536×864 | 1280×720 | 960×540 |
| 2560×1440 | 2560×1440 | 2048×1152 | 1707×960 | 1280×720 |
| 3440×1440 | 3440×1440 | 2752×1152 | 2293×960 | 1720×720 |
| 3840×2160 | 3840×2160 | 3072×1728 | 2560×1440 | 1920×1080 |
Wie man das liest: Wenn Sie einen 4K-Monitor (3840×2160) mit 150 % Skalierung betreiben, sieht eine nicht-DPI-fähige Anwendung einen 2560×1440-Bildschirm. Fragt so eine Anwendung „Wie breit ist der Bildschirm?", bekommt sie 2560 — nicht 3840. Klickt sie auf die Koordinate (1280, 720), übersetzt Windows das in den physischen Pixel (1920, 1080), bevor es an das Display gesendet wird.
Deshalb melden Ihre Bildschirmauflösungs-Vergleichs-Skripte möglicherweise unerwartete Werte — sie sehen die logische Auflösung, nicht die physische.
Das Koordinaten-Versatz-Problem: Wo Ihr Klick tatsächlich landet
Machen wir das konkret. Sie wollen auf die Mitte Ihres 4K-Bildschirms klicken — das ist der physische Pixel (1920, 1080). Aber Ihr Automatisierungstool weiß nichts von DPI-Skalierung. Es berechnet die Mitte dessen, was es sieht — den logischen 2560×1440-Raum — und klickt auf (1280, 720). Windows skaliert diesen Klick dann hoch:
Physischer Klick = logischer Klick × Skalierungsfaktor
Physischer Klick = (1280, 720) × 1.5
Physischer Klick = (1920, 1080) ← zufällig korrekt!
In diesem Fall geht es auf — und das ist kein Zufall. Die Windows-DPI-Virtualisierung skaliert Koordinaten gleichmäßig, sodass jede Position, die als Anteil der Bildschirmgröße berechnet wird (Mitte = 50 %, Ecken = 0 % oder 100 %), unabhängig von der Skalierung korrekt abgebildet wird. Das Desaster schlägt zu, wenn Sie eine absolute Position ansteuern — einen Button, ein Icon, einen bestimmten Pixel —, die kein einfaches Verhältnis zur Bildschirmgröße darstellt:
| Sie wollen klicken (Physisch) | Ihr Skript sendet (Logisch @ 150 %) | OS skaliert zu (Physisch) | Ergebnis |
|---|---|---|---|
| (500, 300) | (500, 300) | (750, 450) | ❌ 250px daneben |
| (960, 540) | (960, 540) | (1440, 810) | ❌ 480px daneben |
| (1920, 1080) | (1280, 720) | (1920, 1080) | ✅ Korrekt |
Das Problem ist offensichtlich: Wenn Ihr Skript Koordinaten aus einem Koordinatensystem verwendet, die Zielanwendung aber ein anderes, ist jeder Klick um den Skalierungsfaktor verschoben. Der Versatz wird umso größer, je weiter Sie von (0, 0) entfernt sind.
Praxisbeispiel: Sie nutzen PyAutoGUI, um einen Button an der logischen Position (500, 300) auf einem mit 150 % skalierten Bildschirm zu klicken. Ihr Skript ist DPI-unfähig, also gibt pyautogui.position() (500, 300) zurück. Der Button liegt aber tatsächlich an der physischen Position (750, 450). Ihr Klick landet bei (750, 450) — was falsch ist, wenn der Button in einer DPI-fähigen Anwendung wie Chrome liegt, die sich selbst mit physischen Koordinaten positioniert.
Der Fix: SetProcessDPIAware und DPI-Awareness
Die Lösung ist ein einziger API-Aufruf — Windows mitteilen, dass Ihre App hochauflösende Displays versteht und physische Pixel möchte:
// C / C++ (Windows API)
SetProcessDPIAware();
// C# (.NET)
[DllImport("user32.dll")]
static extern bool SetProcessDPIAware();
SetProcessDPIAware();
// Python (ctypes)
import ctypes
ctypes.windll.user32.SetProcessDPIAware()
// Python (empfohlen für neuere Windows-Versionen)
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(2) // PROCESS_PER_MONITOR_DPI_AWARE
// Python (empfohlen für Windows 10 1703+ und Windows 11)
import ctypes
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = ctypes.c_void_p(-4)
ctypes.windll.user32.SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)
Nach diesem Aufruf liefern Koordinatenfunktionen physische Pixelwerte statt logische Werte. pyautogui.size() gibt dann 3840×2160 statt 2560×1440 zurück. pyautogui.position() liefert echte Pixelpositionen. Und Ihre Klicks landen genau dort, wo Sie es beabsichtigen.
Welchen Aufruf sollten Sie verwenden?
| API | Verhalten | Am besten für |
|---|---|---|
SetProcessDPIAware() | Systemweite DPI-Awareness. Liefert die physische Auflösung des primären Monitors. | Einzelmonitor-Setups mit einem Skalierungsfaktor. |
SetProcessDpiAwareness(2) | Per-Monitor-DPI-Awareness. Liefert die echte physische Auflösung jedes Monitors. | Multi-Monitor-Setups mit gemischter DPI (Windows 8.1+). |
SetProcessDpiAwarenessContext(-4) | Per-Monitor-DPI-Awareness V2. Wie oben, plus Fehlerbehebungen für Titelleisten und Nicht-Client-Bereiche bei gemischten DPI-Setups. | Empfohlen für Windows 10 1703+ und Windows 11. Siehe unseren Multi-Monitor-Koordinaten-Leitfaden. |
Anwendungsmanifest (ohne Code)
Wenn Sie eine Windows-Anwendung entwickeln, können Sie die DPI-Awareness in Ihrer Manifestdatei deklarieren, anstatt die API aufzurufen:
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
Die vollständige PyAutoGUI-spezifische Lösung mit Multi-Monitor-Unterstützung und Screenshot-Region-Offsets finden Sie in unserem PyAutoGUI-Koordinaten-Leitfaden.
Gemischte DPI-Multi-Monitor: Wenn es richtig kompliziert wird
Zwei Monitore, unterschiedliche Skalierungsfaktoren — sagen wir ein 4K-Laptop-Display mit 150 % und ein externer 1080p-Monitor mit 100 %. Die Koordinatentransformation ändert sich, wenn der Cursor zwischen den Bildschirmen wechselt:
- Auf dem 1080p-Monitor (100 %): logisch = physisch. Kein Versatz.
- Auf dem 4K-Laptopbildschirm (150 %): logische Koordinaten werden durch 1,5 geteilt. Ein physischer Klick auf (2880, 1620) wird nicht-DPI-fähigen Anwendungen als (1920, 1080) gemeldet.
- Wenn Sie ein Fenster von einem Monitor auf den anderen ziehen, skaliert Windows den Koordinatenraum dynamisch um. Nicht-DPI-fähige Anwendungen werden möglicherweise unscharf oder in der falschen Größe dargestellt.
Dieses Setup ist mühsam für die Automatisierung. Aber die Lösung ist immer dieselbe: Rufen Sie SetProcessDpiAwareness(2) für Per-Monitor-DPI-Awareness auf, und Sie erhalten die echten physischen Koordinaten für den Monitor, auf dem sich Ihr Cursor gerade befindet. Die vollständige Koordinatenmathematik für gemischte DPI-Setups steht in unserem Multi-Monitor-Koordinaten-Leitfaden.
Häufig gestellte Fragen
Hat macOS dasselbe DPI-Skalierungs-Problem?
Sozusagen, aber macOS handhabt es eleganter. Retina-Displays haben einen Basisskalierungsfaktor von 2×, und Apps empfangen Koordinaten in „Points" (logische Pixel). Nutzer können jedoch Anzeigemodi wie „Mehr Platz" oder „Größerer Text" in den Systemeinstellungen wählen, was effektive Skalierungsfaktoren wie 1,5× oder 2,4× ergibt — die devicePixelRatio Ihres Browsers spiegelt das wider. Die meisten Mac-Automatisierungstools — AppleScript, Hammerspoon — erledigen die Umrechnung automatisch, sodass das Versatz-Problem unter macOS deutlich seltener auftritt.
Und was ist mit Linux?
Linux-Display-Server (X11 und Wayland) handhaben DPI-Skalierung je nach Compositor und Desktop-Umgebung unterschiedlich. Unter X11 wird die Skalierung oft pro Anwendung über Xft.dpi oder Umgebungsvariablen geregelt. Unter Wayland übernimmt der Compositor die Skalierung. Das Koordinatenverhalten variiert stark — es gibt kein universelles Äquivalent zu SetProcessDPIAware(). Testen Sie Ihre Skripte auf Ihrer spezifischen Linux-Konfiguration.
Warum gibt PyAutoGUI die falsche Bildschirmgröße zurück?
pyautogui.size() liefert unter Windows standardmäßig die logische Auflösung. Auf einem 4K-Display mit 150 % Skalierung gibt es 2560×1440 statt 3840×2160 zurück. Rufen Sie ctypes.windll.user32.SetProcessDPIAware() vor dem Import von PyAutoGUI auf, und es wird die echte physische Auflösung zurückgeben. Das vollständige Setup steht in unserem PyAutoGUI-Koordinaten-Leitfaden.
Wie prüfe ich meinen aktuellen Windows-Skalierungsfaktor?
Klicken Sie mit der rechten Maustaste auf Ihren Desktop → Anzeigeeinstellungen → suchen Sie nach Skalierung und Layout. Der angezeigte Prozentwert (100 %, 125 %, 150 %, 200 %) ist Ihr Skalierungsfaktor. Durch 100 geteilt ergibt den Multiplikator. Oder nutzen Sie unser Tool oben — es ermittelt Ihre DPR automatisch.
Kann ich die Skalierung einfach auf 100 % setzen und das Problem umgehen?
Klar, aber auf einem 4K-Monitor wird dann alles winzig. Ein 27-Zoll-4K-Display mit 100 % liefert etwa 140 PPI — lesbar, aber auf Dauer kein Vergnügen. Sie lösen ein Problem (Koordinaten) und schaffen ein neues (Augenbelastung). Besser: Machen Sie Ihre Skripte DPI-fähig.
Verwandt: Koordinaten plattformuebergreifend pruefen? Unser Tutorial zeigt, wie DPI-Skalierung jede Methode beeinflusst.