[Screen Ruler] Add DIP as an extra measurement unit - #49588
Open
niels9001 wants to merge 2 commits into
Open
Conversation
Show and copy only the selected unit, add per-monitor DIP conversion, and correct the physical-unit fallback. Preserve existing persisted unit values and add focused native, settings, and UI coverage. Co-authored-by: Copilot App <[email protected]> Copilot-Session: 1a6361cf-d701-4a9b-b8e8-d5700c5ba140
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a single measurement-unit setting to the Screen Ruler (MeasureTool) experience, so overlay and clipboard output are rendered in exactly one user-selected unit (Pixels, DIP, Inches, Centimeters, Millimeters), with DIP calculated using the DPI of the monitor containing the measurement.
Changes:
- Updated Settings UI strings/XAML to present a single “Measurement unit” ComboBox option (including DIP).
- Updated MeasureToolCore measurement pipeline to carry per-monitor DPI into conversions/formatting, fix mm fallback conversion, and print one unit (with explicit
pxsuffix). - Added/updated unit tests (native conversion/formatting + settings serialization compatibility) and UITest coverage for DIP clipboard output.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/settings-ui/Settings.UI/Strings/en-us/Resources.resw | Updates Settings strings for the new single measurement-unit setting and adds DIP option text. |
| src/settings-ui/Settings.UI/SettingsXAML/Views/MeasureToolPage.xaml | Adds an AutomationId and appends the DIP option to the measurement unit ComboBox. |
| src/settings-ui/Settings.UI.UnitTests/ModelsTests/MeasureToolSettingsTests.cs | Adds serialization/compatibility coverage for unit index persistence (including DIP). |
| src/modules/MeasureTool/Tests/ScreenRuler.UITests/TestHelper.cs | Adds UI helper to set measurement unit and tightens clipboard validation to include explicit unit suffixes. |
| src/modules/MeasureTool/Tests/ScreenRuler.UITests/TestBounds.cs | Adds a UITest validating DIP clipboard output for the bounds tool. |
| src/modules/MeasureTool/Tests/MeasureToolCore.UnitTests/MeasureToolCore.UnitTests.vcxproj | Introduces a native unit test project for MeasureToolCore conversion/formatting logic. |
| src/modules/MeasureTool/Tests/MeasureToolCore.UnitTests/MeasurementLogicTests.cpp | Adds focused native tests for DPI/DIP conversion, physical-unit fallback, and formatting behavior. |
| src/modules/MeasureTool/MeasureToolUI/Strings/en-us/Resources.resw | Adds the DIP abbreviation resource used by the overlay/clipboard formatter. |
| src/modules/MeasureTool/MeasureToolCore/ToolState.h | Adds a helper to retrieve per-window monitor DPI to support DIP conversion. |
| src/modules/MeasureTool/MeasureToolCore/ScreenCapturing.cpp | Plumbs monitor DPI into captured measurements so conversions can be DPI-aware. |
| src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj.filters | Adds MeasurementLogic.h to the project filters. |
| src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj | Adds MeasurementLogic.h to the project includes. |
| src/modules/MeasureTool/MeasureToolCore/MeasureToolOverlayUI.cpp | Switches overlay formatting to show only the selected unit (no forced pixel output). |
| src/modules/MeasureTool/MeasureToolCore/MeasurementLogic.h | Adds shared conversion + formatting helper functions (including DIP + corrected mm fallback). |
| src/modules/MeasureTool/MeasureToolCore/Measurement.h | Refactors Measurement to use MeasurementLogic and carry monitor DPI for conversions. |
| src/modules/MeasureTool/MeasureToolCore/Measurement.cpp | Updates conversion/printing to use the shared formatter and include explicit unit suffix. |
| src/modules/MeasureTool/MeasureToolCore/BoundsToolOverlayUI.cpp | Plumbs monitor DPI into bounds measurements and prints only the selected unit. |
| PowerToys.slnx | Adds the new MeasureToolCore native unit test project to the solution. |
| doc/devdocs/modules/screenruler.md | Updates module documentation to reflect the expanded unit support (including DIP). |
Co-authored-by: Copilot App <[email protected]> Copilot-Session: 1a6361cf-d701-4a9b-b8e8-d5700c5ba140
niels9001
marked this pull request as ready for review
July 31, 2026 10:39
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/modules/MeasureTool/MeasureToolCore/BoundsToolOverlayUI.cpp:88
GetKeyState(VK_SHIFT)checks the high-order bit (0x8000). Using0x80000works only due to sign-extension quirks and is inconsistent with the same check in MeasureToolOverlayUI.cpp, making the intent unclear and potentially fragile if the return value is cast/handled differently.
if (const bool shiftPress = GetKeyState(VK_SHIFT) & 0x80000; shiftPress && perScreen.currentBounds)
src/modules/MeasureTool/Tests/ScreenRuler.UITests/TestHelper.cs:456
- The clipboard can contain multiple measurements separated by newlines (BoundsToolOverlayUI appends
perScreen.measurementsplus the current selection, andSetClipboardToMeasurementsprints each measurement on its own line). Anchoring the regex to the full clipboard string (^...$) makes this assertion brittle if any prior measurements are present. Consider validating each non-empty line instead, and ensure none of the lines include the pixel suffix.
Assert.IsTrue(
Regex.IsMatch(
clipboardText,
$@"^\d+(?:\.\d+)?\s*[x×]\s*\d+(?:\.\d+)?\s+{Regex.Escape(expectedUnit)}$"),
$"Clipboard should contain one {expectedUnit} measurement, but contained: '{clipboardText}'");
Assert.IsFalse(clipboardText.Contains(" px", StringComparison.Ordinal), "Clipboard should not include an extra pixel measurement");
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of the Pull Request
Adds display-independent pixels (DIP) to Screen Ruler's existing Extra units of measurement setting. Physical pixels remain the primary overlay value; selecting DIP adds a second, parenthesized measurement that adjusts for Windows display scaling.
DIP values use the DPI of the monitor containing the measurement. This also corrects the millimeter fallback conversion when physical monitor dimensions are unavailable.
Before vs after:
PR Checklist
Detailed Description of the Pull Request / Additional comments
4.Validation Steps Performed
MeasureToolCorefor ARM64 Debug.MeasureToolUIfor ARM64 Debug.MeasureToolCore.UnitTests: 5 passed.ScreenRuler.UITests; local execution was not run because WinAppDriver is not installed.