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

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 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 and implemented in 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 (lines 29-40) handles the callback mechanism and sorting logic:

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 (lines 42-54), this method returns a MonitorInfo instance ready for immediate use:

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 (lines 56-66):

// 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) 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 (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 (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 (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 (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.

#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 Declaration of Box and MonitorInfo (public API).
src/common/Display/monitors.cpp Implementation of enumeration, primary-monitor logic, size queries, and conversion helpers.
src/common/monitor_utils.h Generic template helpers for extracting arbitrary RECT members from MONITORINFO.
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 Real-world use: creates per-monitor overlay UI and capture threads.
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 (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 (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 (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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →