Quick answer: Declare Per-Monitor v2 DPI awareness via manifest or SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2). Handle WM_DPICHANGED to rescale UI and swapchain on transition.
Players with a 4K monitor + a 1080p second monitor report your game crashing when they drag the window between the two. Different DPI scales (200% vs 100%) trigger Windows’ DPI change message; if the game doesn’t handle it, internal state desyncs.
DPI Awareness Levels
- Unaware: Windows bitmap-stretches the window. Blurry at high DPI.
- System Aware: app uses primary monitor’s DPI for the lifetime. Wrong scale on secondary monitors.
- Per-Monitor v1: receives WM_DPICHANGED; must handle scaling.
- Per-Monitor v2 (recommended): WM_DPICHANGED + child window scaling. Modern apps target this.
Declare Awareness via Manifest
<assembly ...>
<application>
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>
Embed in your executable via mt.exe or link-time settings.
Or via Code
#include <ShellScalingAPI.h>
int main() {
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
// initialize the rest
}
Call before any window creation. Modern Windows; older might need SetProcessDpiAwareness.
Handle WM_DPICHANGED
case WM_DPICHANGED: {
const RECT* suggestedRect = (RECT*)lparam;
SetWindowPos(hwnd, nullptr,
suggestedRect->left, suggestedRect->top,
suggestedRect->right - suggestedRect->left,
suggestedRect->bottom - suggestedRect->top,
SWP_NOZORDER | SWP_NOACTIVATE);
RescaleUI(LOWORD(wparam)); // new DPI
return 0;
}
Windows suggests a new window rect that accounts for the new DPI. Use it; rescale your UI elements to the new DPI.
Engine Specifics
- Unity: usually Per-Monitor v2 by default in recent versions; verify in Player Settings.
- Unreal: handles via Slate; should work out of the box.
- SDL2: pass SDL_WINDOW_ALLOW_HIGHDPI; handle SDL_WINDOWEVENT_SIZE_CHANGED.
Verifying
Connect a second monitor at a different scale (Display Settings → adjust each). Drag the game window between them. No crash, UI rescales correctly. Cursor coordinates remain accurate.
“Per-monitor DPI is now the default desktop setup. Declare awareness, handle WM_DPICHANGED, rescale UI.”
Test multi-monitor configurations early — players with mixed DPI setups are common and the bug is easy to miss in single-monitor dev.