# Using MonitorInfo to Detect and Manage Multi-Monitor Configurations in PowerToys

> Learn how to use MonitorInfo in PowerToys to detect and manage multi-monitor configurations. This C++ abstraction simplifies display layout detection and DPI scaling.

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

---

**The `MonitorInfo` class in Microsoft's PowerToys provides a C++ abstraction over Win32 monitor enumeration APIs, enabling modules to detect display layouts, identify primary screens, and handle per-monitor DPI scaling through a consistent interface located in `src/common/Display`.**

Managing multi-monitor setups in Windows requires handling complex Win32 API calls for enumeration, geometry queries, and DPI awareness. The PowerToys repository solves this challenge by implementing the `MonitorInfo` utility class, which wraps `HMONITOR` handles and `MONITORINFOEX` structures into a testable, reusable component. This article explores how to use MonitorInfo to detect and manage multi-monitor configurations by examining its source implementation in [`src/common/Display/monitors.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.cpp) and its integration across PowerToys modules.

## What Is the MonitorInfo Class?

The `MonitorInfo` class serves as the central abstraction for display management within PowerToys. Located in [`src/common/Display/monitors.h`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.h) and implemented in [`src/common/Display/monitors.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.cpp), this class encapsulates a `HMONITOR` handle alongside its associated `MONITORINFOEX` structure.

By wrapping these Win32 primitives, `MonitorInfo` provides thread-safe, RAII-friendly access to monitor properties without requiring module developers to manually manage API calls or buffer allocations. The class also integrates with the `Box` helper to provide geometric operations on monitor rectangles.

## Core Capabilities of MonitorInfo

### Enumerating All Displays

To retrieve an ordered list of all connected displays, `MonitorInfo` implements the static method `GetMonitors`. This function calls `EnumDisplayMonitors` and sorts the resulting collection by screen position, ensuring a left-to-right ordering that matches the Windows virtual desktop layout.

The implementation in [`src/common/Display/monitors.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.cpp) (lines 29-40) handles the callback mechanism and sorting logic:

```cpp
const auto monitors = MonitorInfo::GetMonitors(true);   // true → include non-working area
for (size_t i = 0; i < monitors.size(); ++i)
{
    const auto& mi = monitors[i];
    const auto box = mi.GetScreenSize(true);
    std::cout << "Monitor " << i
              << " : [" << box.left() << "," << box.top() << "] - ["
              << box.right() << "," << box.bottom() << "]\n";
}

```

### Detecting the Primary Monitor

The `GetPrimaryMonitor` static method scans the enumerated list for the display bearing the `MONITORINFOF_PRIMARY` flag. This abstraction eliminates the need for manual flag checking and provides a consistent reference point for modules that must anchor UI elements to the main display.

Found in [`src/common/Display/monitors.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.cpp) (lines 42-54), this method returns a `MonitorInfo` instance ready for immediate use:

```cpp
const auto primary = MonitorInfo::GetPrimaryMonitor();
const auto size = primary.GetSize();
std::cout << "Primary monitor physical: " << size.width_physical
          << "×" << size.height_physical << " pixels\n";
std::cout << "Logical (device-independent): " << size.width_logical
          << "×" << size.height_logical << "\n";

```

### Resolving Monitors from Windows and Points

For context-aware operations, `MonitorInfo` provides `GetFromWindow` and `GetFromPoint`. These wrap `MonitorFromWindow` and `MonitorFromPoint`, converting handles into fully populated `MonitorInfo` objects. This pattern supports scenarios like snapping utilities to the display containing the cursor or a specific application window.

The implementation resides in [`src/common/Display/monitors.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.cpp) (lines 56-66):

```cpp
// Get the monitor that contains a screen point (e.g. mouse cursor)
MonitorInfo MonitorFromPoint(int x, int y)
{
    return MonitorInfo::GetFromPoint(x, y);
}

```

### Querying Physical and Logical Sizes

Modern displays require handling both physical pixel dimensions and logical DPI-scaled units. The `GetSize` method (lines 68-94 in [`monitors.cpp`](https://github.com/microsoft/PowerToys/blob/main/monitors.cpp)) queries `GetDeviceCaps` and `EnumDisplaySettingsEx` to populate a structure containing:

- Physical pixel width and height
- Logical (device-independent) dimensions
- Millimeter dimensions for physical size calculations

This enables modules to render content at the correct scale regardless of the display's DPI configuration.

## Helper Classes and Utilities

### The Box Geometry Helper

The `Box` class, defined in [`src/common/Display/monitors.h`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.h) (lines 10-42), encapsulates a Win32 `RECT` structure with geometric utility methods. Unlike raw rectangles, `Box` provides:

- Width and height calculations
- Point containment testing
- Comparison operators for sorting
- Union and intersection operations

This abstraction simplifies layout calculations when positioning windows across multiple displays.

### Template Utilities for RECT Extraction

For advanced scenarios requiring arbitrary rectangle extraction from `MONITORINFO`, [`src/common/monitor_utils.h`](https://github.com/microsoft/PowerToys/blob/main/src/common/monitor_utils.h) (lines 5-25) provides template functions `GetAllMonitorRects` and `GetAllMonitorInfo`. These utilities allow generic extraction of any `RECT` member (work area, monitor area, etc.) without duplicating enumeration logic.

## Real-World Usage in PowerToys Modules

### Shortcut Guide Overlay Placement

The Shortcut Guide module demonstrates multi-monitor geometry aggregation. Located in [`src/modules/ShortcutGuide/ShortcutGuide/overlay_window.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/ShortcutGuide/ShortcutGuide/overlay_window.cpp) (lines 41-50), the code retrieves all monitors via `MonitorInfo::GetMonitors(true)`, then merges individual rectangles into a single `Box` representing the total virtual desktop. This ensures the overlay centers correctly across all displays rather than appearing on a single screen.

### Measure Tool Per-Monitor Capture

The Measure Tool illustrates per-monitor UI instantiation. In [`src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp) (lines 5-7 and 46-48), the tool enumerates displays using `MonitorInfo::GetMonitors(true)`, then iterates the collection to spawn separate overlay windows and capture threads for each monitor. This pattern ensures accurate screen measurements regardless of which display contains the target content.

## Implementation Examples

The following self-contained examples demonstrate common operations using the PowerToys `MonitorInfo` API. These patterns can be integrated into any C++ module within the PowerToys ecosystem.

```cpp
#include "common/Display/monitors.h"
#include <iostream>

// 1. List all monitors with basic geometry
void ListMonitors()
{
    const auto monitors = MonitorInfo::GetMonitors(true);   // true → include non-working area
    for (size_t i = 0; i < monitors.size(); ++i)
    {
        const auto& mi = monitors[i];
        const auto box = mi.GetScreenSize(true);
        std::cout << "Monitor " << i
                  << " : [" << box.left() << "," << box.top() << "] - ["
                  << box.right() << "," << box.bottom() << "]\n";
    }
}

// 2. Find the primary monitor and print its physical resolution
void PrintPrimaryInfo()
{
    const auto primary = MonitorInfo::GetPrimaryMonitor();
    const auto size = primary.GetSize();
    std::cout << "Primary monitor physical: " << size.width_physical
              << "×" << size.height_physical << " pixels\n";
    std::cout << "Logical (device-independent): " << size.width_logical
              << "×" << size.height_logical << "\n";
}

// 3. Get the monitor that contains a screen point (e.g. mouse cursor)
MonitorInfo MonitorFromPoint(int x, int y)
{
    return MonitorInfo::GetFromPoint(x, y);
}

// 4. Compute the bounding rectangle that encloses *all* monitors.
//    Useful for centering a window spanning the entire virtual desktop.
Box ComputeVirtualDesktop()
{
    const auto monitors = MonitorInfo::GetMonitors(true);
    Box total = monitors.front().GetScreenSize(true);
    for (const auto& m : monitors)
    {
        const auto sz = m.GetScreenSize(true);
        total.rect.left   = std::min(total.left(),   sz.left());
        total.rect.top    = std::min(total.top(),    sz.top());
        total.rect.right  = std::max(total.right(),  sz.right());
        total.rect.bottom = std::max(total.bottom(), sz.bottom());
    }
    return total;
}

```

## Key Source Files

| Path | Role |
|------|------|
| [`src/common/Display/monitors.h`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.h) | Declaration of `Box` and `MonitorInfo` (public API). |
| [`src/common/Display/monitors.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.cpp) | Implementation of enumeration, primary-monitor logic, size queries, and conversion helpers. |
| [`src/common/monitor_utils.h`](https://github.com/microsoft/PowerToys/blob/main/src/common/monitor_utils.h) | Generic template helpers for extracting arbitrary `RECT` members from `MONITORINFO`. |
| [`src/modules/ShortcutGuide/ShortcutGuide/overlay_window.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/ShortcutGuide/ShortcutGuide/overlay_window.cpp) | Real-world use: computes a unified screen rectangle for overlay placement. |
| [`src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp) | Real-world use: creates per-monitor overlay UI and capture threads. |
| [`doc/devdocs/tools/monitor-info-report.md`](https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/tools/monitor-info-report.md) | Diagnostic tool that logs the same WinAPI information used by the library. |

## Summary

- **The `MonitorInfo` class** in `src/common/Display` abstracts Win32 `HMONITOR` handles into a safe, queryable C++ interface for PowerToys modules.
- **Enumeration methods** like `GetMonitors()` and `GetPrimaryMonitor()` provide sorted, ready-to-use display lists without manual API calls.
- **Geometry helpers** including the `Box` class and `GetSize()` method handle both physical pixels and logical DPI-scaled units across heterogeneous monitor setups.
- **Real-world implementations** in Shortcut Guide and Measure Tool demonstrate the pattern: enumerate displays, compute geometry, then spawn per-monitor UI or capture threads.

## Frequently Asked Questions

### How does MonitorInfo handle DPI scaling across different monitors?

The `GetSize()` method in [`src/common/Display/monitors.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.cpp) (lines 68-94) queries both physical pixel dimensions via `GetDeviceCaps` and logical device-independent pixels through `EnumDisplaySettingsEx`. This dual-query approach allows PowerToys modules to render content at the correct scale regardless of whether a display uses 96 DPI, 144 DPI, or variable scaling factors.

### What is the difference between GetMonitors(true) and GetMonitors(false)?

The boolean parameter passed to `MonitorInfo::GetMonitors` determines whether the returned `Box` rectangles represent the entire monitor surface (`true`) or only the working area (`false`). The working area excludes taskbars and other docked windows, making `GetMonitors(false)` ideal for window placement logic, while `GetMonitors(true)` is preferred for full-screen overlays or screen capture utilities.

### How can I determine which monitor contains a specific window?

Use the static method `MonitorInfo::GetFromWindow(HWND hwnd)` defined in [`src/common/Display/monitors.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.cpp) (lines 56-66). This wrapper around `MonitorFromWindow` returns a fully populated `MonitorInfo` instance containing the display's geometry, DPI settings, and primary status, eliminating the need to manually correlate window handles with display indices.

### Why does PowerToys use a Box class instead of raw RECT structures?

The `Box` class defined in [`src/common/Display/monitors.h`](https://github.com/microsoft/PowerToys/blob/main/src/common/Display/monitors.h) (lines 10-42) encapsulates Win32 `RECT` structures with geometric utility methods including width/height calculations, point containment tests, and comparison operators. This abstraction simplifies layout calculations when positioning windows across multiple displays and ensures consistent sorting behavior when `MonitorInfo` enumerates displays left-to-right.