# Implementing DPI-Aware Functionality in PowerToys Modules Using DPIAware

> Learn how PowerToys modules implement DPI aware functionality using DPIAware. Discover how to enable per-monitor DPI awareness and convert UI coordinates efficiently.

- Repository: [Microsoft/PowerToys](https://github.com/microsoft/PowerToys)
- Tags: how-to-guide
- Published: 2026-02-25

---

**PowerToys modules achieve per-monitor DPI awareness by calling `DPIAware::EnableDPIAwarenessForThisProcess()` at startup and using conversion helpers like `DPIAware::Convert()` to scale UI coordinates between logical (96 DPI) and physical pixels.**

PowerToys requires pixel-perfect rendering across displays with varying scaling factors. The centralized `DPIAware` utility in `src/common/Display` abstracts Win32 DPI APIs, providing a testable interface that modules use instead of calling `GetDpiForMonitor` or `SetProcessDpiAwarenessContext` directly.

## Understanding the DPIAware Architecture

The `DPIAware` namespace in [`src/common/Display/dpi_aware.h`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/dpi_aware.h) encapsulates all DPI-related functionality. The implementation in [`src/common/Display/dpi_aware.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/dpi_aware.cpp) wraps the modern Shell Scaling API, handling per-monitor awareness and coordinate conversion.

Key components include:

- **`EnableDPIAwarenessForThisProcess`**: Sets process-wide DPI awareness
- **`GetScreenDPIForMonitor`** and **`GetScreenDPIForWindow`**: Retrieve scaling factors
- **`Convert`** and **`InverseConvert`**: Transform between logical and physical coordinates
- **`ConvertByCursorPosition`**: Scale based on the monitor under the cursor

## Enabling Per-Monitor DPI Awareness

Every PowerToys executable must opt into per-monitor-v2 DPI awareness before creating any UI. This is done exactly once per process.

In [`src/runner/main.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/runner/main.cpp) at line 184, the Runner initializes awareness:

```cpp
#include "dpi_aware.h"

int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    DPIAware::EnableDPIAwarenessForThisProcess();  // Required for per-monitor-v2
    // ... create window and run message loop
}

```

The implementation calls `SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)` as seen in lines 31-33 of [`src/common/Display/dpi_aware.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/dpi_aware.cpp).

## Converting Coordinates and Dimensions

After enabling awareness, modules must convert logical coordinates (based on 96 DPI) to physical pixels for the specific monitor displaying the window.

### Window-Based Scaling

Use `DPIAware::Convert` when you have a window handle and need to scale dimensions or rectangles to the monitor containing that window.

From [`src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp) at line 317:

```cpp
#include "dpi_aware.h"

void ScaleWindowRect(HWND hwnd, RECT& rect)
{
    // Convert logical coordinates (96 DPI) to physical pixels
    DPIAware::Convert(hwnd, rect);
}

```

The `Convert` method accepts both `HWND` and `HMONITOR`, allowing usage even before window creation if you have a monitor handle.

### Cursor-Based Scaling

When positioning UI based on the current mouse location (such as context menus or floating toolbars), use cursor-based helpers to get the DPI of the monitor under the cursor.

From [`src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp) at line 128:

```cpp
#include "dpi_aware.h"

void ResizeBasedOnCursor(float& width, float& height)
{
    DPIAware::ConvertByCursorPosition(width, height);
}

```

Similarly, [`src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.cpp) at line 10 retrieves DPI for an existing window:

```cpp
auto res = DPIAware::GetScreenDPIForWindow(window, dpi);

```

## Integration Examples from PowerToys Modules

The DPIAware utility provides a consistent pattern across all PowerToys modules:

- **Runner** ([`src/runner/main.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/runner/main.cpp)): Initializes process-wide awareness before any UI creation
- **FancyZones** ([`src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp)): Scales zone rectangles using `Convert` and `InverseConvert`
- **Keyboard Manager** ([`src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp)): Adapts editor window size based on cursor position using `ConvertByCursorPosition`
- **Always-On-Top** ([`src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/alwaysontop/AlwaysOnTop/ScalingUtils.cpp)): Retrieves monitor-specific DPI for window scaling using `GetScreenDPIForWindow`

## Summary

- **Enable awareness early**: Call `DPIAware::EnableDPIAwarenessForThisProcess()` once at process startup before creating any windows.
- **Use conversion helpers**: Scale logical coordinates to physical pixels using `DPIAware::Convert` for window-based operations or `DPIAware::ConvertByCursorPosition` for cursor-based positioning.
- **Centralized implementation**: All DPI logic lives in [`src/common/Display/dpi_aware.h`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/dpi_aware.h) and [`src/common/Display/dpi_aware.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/dpi_aware.cpp), ensuring consistent behavior across PowerToys modules.
- **Testable abstraction**: The helper functions wrap Win32 APIs like `GetDpiForMonitor` and `SetProcessDpiAwarenessContext`, providing a mockable interface for unit testing.

## Frequently Asked Questions

### When should I call EnableDPIAwarenessForThisProcess?

You must call `DPIAware::EnableDPIAwarenessForThisProcess()` exactly once per executable, before any UI thread creates windows or accesses display metrics. In PowerToys, this happens in [`src/runner/main.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/runner/main.cpp) at line 184 and in each module's entry point that creates its own process.

### How do I handle DPI changes when moving a window between monitors?

Use `DPIAware::Convert` with the window handle when positioning or sizing the window. The function automatically retrieves the DPI for the monitor containing the window. For operations based on mouse position (like showing a context menu), use `DPIAware::ConvertByCursorPosition` to get the DPI of the monitor currently under the cursor.

### What is the difference between Convert and InverseConvert?

`DPIAware::Convert` transforms logical coordinates (based on 96 DPI) into physical pixels for the target monitor. `DPIAware::InverseConvert` performs the reverse operation, converting physical pixel measurements back to logical coordinates. FancyZones uses both when calculating zone layouts and converting them to window positions.

### Can I use DPIAware in a new PowerToys module?

Yes. Include `#include "dpi_aware.h"` from `src/common/Display` in your module's source files. Call `DPIAware::EnableDPIAwarenessForThisProcess()` at startup if your module runs in its own process, then use `DPIAware::Convert` or `DPIAware::GetScreenDPIForWindow` whenever you need to scale UI elements to the current monitor's DPI.