From 30b66c1d0d96ff6f0d35085e3b6b0ebcb818e77c Mon Sep 17 00:00:00 2001 From: "Simon Zhao (BEYONDSOFT CONSULTING INC)" Date: Fri, 29 May 2026 14:13:31 +0800 Subject: [PATCH 1/2] Fix MaskedTextBox PropertyGrid text editor DPI scaling at runtime --- .../Design/MaskedTextBoxTextEditorDropDown.cs | 4 ++-- .../MaskedTextBoxTextEditorDropDownTests.cs | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDown.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDown.cs index 54ac9049bb7..a18daad38e7 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDown.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDown.cs @@ -48,8 +48,8 @@ public MaskedTextBoxTextEditorDropDown(MaskedTextBox maskedTextBox) BackColor = Drawing.SystemColors.Control; BorderStyle = BorderStyle.FixedSingle; Name = "MaskedTextBoxTextEditorDropDown"; - Padding = new Padding(16); - Size = new Drawing.Size(100, 52); + Padding = new Padding(LogicalToDeviceUnits(16)); + Size = LogicalToDeviceUnits(new Drawing.Size(100, 52)); ((System.ComponentModel.ISupportInitialize)(_errorProvider)).EndInit(); ResumeLayout(false); PerformLayout(); diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDownTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDownTests.cs index 617e9a797ba..a6b14ab10dd 100644 --- a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDownTests.cs +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDownTests.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Drawing; + namespace System.Windows.Forms.Design.Tests; public class MaskedTextBoxTextEditorDropDownTests @@ -54,4 +56,20 @@ public void MaskInputRejected_SetsError_WhenInputRejected() dropDownMaskedTextBox.Text = "invalid"; errorProvider.GetError(dropDownMaskedTextBox).Should().Contain(SR.MaskedTextBoxHintDigitExpected); } + + [Fact] + public void DropDown_SizeAndPadding_ScalesWithDPI() + { + using MaskedTextBox maskedTextBox = new(); + using MaskedTextBoxTextEditorDropDown dropDown = new(maskedTextBox); + + // The size and padding should be scaled based on DPI + // At 96 DPI (100%), Size should be (100, 52) and Padding should be (16, 16, 16, 16) + // At higher DPI, these values should scale proportionally + Size expectedSize = dropDown.LogicalToDeviceUnits(new Size(100, 52)); + Padding expectedPadding = new(dropDown.LogicalToDeviceUnits(16)); + + dropDown.Size.Should().Be(expectedSize); + dropDown.Padding.Should().Be(expectedPadding); + } } From 3c75c59edf59e0842446cf81572ea960859c144e Mon Sep 17 00:00:00 2001 From: "Simon Zhao (BEYONDSOFT CONSULTING INC)" Date: Mon, 15 Jun 2026 15:06:59 +0800 Subject: [PATCH 2/2] Handle feedback --- .../Design/MaskedTextBoxTextEditorDropDown.cs | 22 +++++++++++++++++-- .../MaskedTextBoxTextEditorDropDownTests.cs | 11 ++++------ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDown.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDown.cs index a18daad38e7..538014edd98 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDown.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDown.cs @@ -5,6 +5,11 @@ namespace System.Windows.Forms.Design; internal class MaskedTextBoxTextEditorDropDown : UserControl { + // Logical (96 DPI) constants. The actual device-pixel values are recomputed in + // RescaleConstantsForDpi so that PerMonitorV2 DPI changes are honoured. + private const int LogicalPadding = 16; + private static readonly Drawing.Size s_logicalSize = new(100, 52); + private bool _cancel; private readonly MaskedTextBox _cloneMtb; private readonly ErrorProvider _errorProvider; @@ -48,8 +53,11 @@ public MaskedTextBoxTextEditorDropDown(MaskedTextBox maskedTextBox) BackColor = Drawing.SystemColors.Control; BorderStyle = BorderStyle.FixedSingle; Name = "MaskedTextBoxTextEditorDropDown"; - Padding = new Padding(LogicalToDeviceUnits(16)); - Size = LogicalToDeviceUnits(new Drawing.Size(100, 52)); + + // Apply the initial DPI-scaled padding/size. Subsequent DPI changes are + // picked up automatically through RescaleConstantsForDpi. + RescaleConstantsForDpi(DeviceDpi, DeviceDpi); + ((System.ComponentModel.ISupportInitialize)(_errorProvider)).EndInit(); ResumeLayout(false); PerformLayout(); @@ -80,6 +88,16 @@ protected override bool ProcessDialogKey(Keys keyData) return base.ProcessDialogKey(keyData); } + protected override void RescaleConstantsForDpi(int deviceDpiOld, int deviceDpiNew) + { + base.RescaleConstantsForDpi(deviceDpiOld, deviceDpiNew); + + // DeviceDpi has already been updated to deviceDpiNew by the framework before + // this call, so LogicalToDeviceUnits returns values scaled to the new DPI. + Padding = new Padding(LogicalToDeviceUnits(LogicalPadding)); + Size = LogicalToDeviceUnits(s_logicalSize); + } + private void maskedTextBox_MaskInputRejected(object? sender, MaskInputRejectedEventArgs e) { _errorProvider.SetError(_cloneMtb, MaskedTextBoxDesigner.GetMaskInputRejectedErrorMessage(e)); diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDownTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDownTests.cs index a6b14ab10dd..92322d30e2f 100644 --- a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDownTests.cs +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MaskedTextBoxTextEditorDropDownTests.cs @@ -63,13 +63,10 @@ public void DropDown_SizeAndPadding_ScalesWithDPI() using MaskedTextBox maskedTextBox = new(); using MaskedTextBoxTextEditorDropDown dropDown = new(maskedTextBox); - // The size and padding should be scaled based on DPI - // At 96 DPI (100%), Size should be (100, 52) and Padding should be (16, 16, 16, 16) - // At higher DPI, these values should scale proportionally - Size expectedSize = dropDown.LogicalToDeviceUnits(new Size(100, 52)); - Padding expectedPadding = new(dropDown.LogicalToDeviceUnits(16)); + // Simulate a DPI change and verify that the dropdown recomputes its logical constants. + dropDown.TestAccessor.Dynamic.RescaleConstantsForDpi(96, 192); - dropDown.Size.Should().Be(expectedSize); - dropDown.Padding.Should().Be(expectedPadding); + dropDown.Size.Should().Be(new Size(100, 52)); + dropDown.Padding.Should().Be(new Padding(16)); } }