Skip to content

Fix issue 14449: ToolStrip DPI change issue in .NET 10#14454

Open
SimonZhao888 wants to merge 3 commits intodotnet:mainfrom
SimonZhao888:Fix_issue_14449
Open

Fix issue 14449: ToolStrip DPI change issue in .NET 10#14454
SimonZhao888 wants to merge 3 commits intodotnet:mainfrom
SimonZhao888:Fix_issue_14449

Conversation

@SimonZhao888
Copy link
Copy Markdown
Member

@SimonZhao888 SimonZhao888 commented Apr 8, 2026

Fixes #14449

When we drag the ToolStrip control on screens with different DPI settings, the call stack history is WmDpiChangedBeforeParent -> RescaleConstantsForDpi. However, within the WmDpiChangedBeforeParent method, OriginalDeviceDpiInternal and DeviceDpiInternal retrieve the same value, which will cause the RescaleConstantsForDpi method in the ToolStrip class to fail to execute as expected.

Proposed changes

  • OriginalDeviceDpiInternal = DeviceDpiInternal; is effectively a no-op in the common case: the setter uses DeviceDpiInternal as the default value to remove the stored property, so after DeviceDpiInternal is updated later in this method, OriginalDeviceDpiInternal will again resolve to the new DPI. This means other code that relies on OriginalDeviceDpiInternal != DeviceDpiInternal during/after the DPI-change path will still observe them as equal. So consider capturing oldDeviceDpi first, updating DeviceDpiInternal to the new DPI, and then assigning OriginalDeviceDpiInternal = oldDeviceDpi so it is persisted (mirroring how Form sets OriginalDeviceDpiInternal = e.DeviceDpiOld).

Customer Impact

  • ToolStrip DPI change correctly in .NET 10.

Regression?

  • Yes

Risk

-Minimal

Screenshots

Before

image

After

image image

Test methodology

  • Manually

Test environment(s)

  • 11.0.100-preview.3.26170.106
Microsoft Reviewers: Open in CodeFlow

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to fix a .NET 10 regression where ToolStrip DPI change handling uses an incorrect “old DPI” value by adjusting how Control.OriginalDeviceDpiInternal is retrieved.

Changes:

  • Updated Control.OriginalDeviceDpiInternal getter logic in an attempt to prevent it from incorrectly returning DeviceDpiInternal when computing the old DPI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@LeafShi1
Copy link
Copy Markdown
Member

LeafShi1 commented Apr 8, 2026

Hi @SimonZhao888, thanks for the fix! I've reviewed the changes and have a few observations:

1. The fix correctly addresses the root cause
The OriginalDeviceDpiInternal property uses PropertyStore with DeviceDpiInternal as the default/removal value. This means:

  • The getter defaults to DeviceDpiInternal when no value is stored
  • The setter (via AddOrRemoveValue) removes the stored value when it equals DeviceDpiInternal

In the original code, after DeviceDpiInternal = newDeviceDpi, the getter for OriginalDeviceDpiInternal would return the new DPI (since the stored value was removed), making RescaleConstantsForDpi(sameDPI, sameDPI) a no-op. Your fix correctly captures the old DPI before updating and restores it afterward.

2. Consider adding a code comment for the first assignment (line 11566)
The line OriginalDeviceDpiInternal = DeviceDpiInternal; may appear redundant with the new code, but it serves an important purpose: it clears any stale OriginalDeviceDpiInternal from a prior DPI change, ensuring the early return check (OriginalDeviceDpiInternal == newDeviceDpi) correctly reflects the current DPI. A brief inline comment would help future maintainers understand why this line is still needed.

3. Broader test coverage
This change is in Control.cs, the base class for all WinForms controls. The PR description mentions only manual testing with ToolStrip. Have other controls been tested — particularly those that override RescaleConstantsForDpi (e.g., ToolStripDropDownMenu, ToolStripMenuItem, DataGridView, PropertyGrid)? Since this affects the DPI handling path for all child controls, broader validation would increase confidence.

4. Automated regression test
Given this is a regression in .NET 10, an automated test for WM_DPICHANGED_BEFOREPARENT handling would help prevent recurrence. Could a test be added that verifies RescaleConstantsForDpi receives distinct old/new DPI values when the DPI actually changes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-DarkMode Issues relating to Dark Mode feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[.NET 10][High DPI][Regression]ToolStrip DPI change issue in .NET 10

3 participants