Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5e80a18
Improve Net11 TextBox text layout by reducing excess vertical whitespace
Aug 13, 2026
4be2e92
Handling the issue of incomplete text display for TextBox and Numeric…
Aug 13, 2026
6c30a11
Adjust the height of the ComboBox control in .NET 1.1.
Aug 14, 2026
66261ac
Adjusting the radian angle of a text box in Net11 mode
Aug 14, 2026
7417187
Adjust the outer border length of controls like UpDown to minimize th…
Aug 14, 2026
281cffa
Handle the failed test cases
Aug 17, 2026
e69291a
Handle Copilot feedback
Aug 17, 2026
66d1218
Ensure the borders of Net11 Modern rounded-corner controls remain thi…
Aug 18, 2026
f184e24
Handle failure test cases
Aug 18, 2026
17946ca
Merge branch 'dotnet:main' into fix/textbox-display-whitespace
SimonZhao888 Aug 24, 2026
351432c
Increase the bottom height of textbox when the control is focused.
Aug 24, 2026
4c6c4b3
The height of controls like Edit in Net11 mode has been readjusted so…
Aug 26, 2026
7244666
Adjust the size of the DataGridViewComboBoxCell; adjust the size of t…
Aug 27, 2026
ceb8733
Fixed an issue where text was obscured at certain scales.
Aug 27, 2026
a7ba88d
Remove empty line
Aug 28, 2026
89a6264
Fixed the issue of inconsistent height of ComboBox when DropDownStyle…
Aug 28, 2026
ecc17db
Fixed an issue where the initial horizontal scroll position was incor…
Aug 28, 2026
2580f7d
Merge branch 'main' into fix/textbox-display-whitespace
Aug 28, 2026
5367316
Handle conflicts
Aug 28, 2026
c53a9fa
Fix issue: ComboBox text appears vertically misaligned in DropDown mo…
Sep 1, 2026
6c867dd
Remove DataGridView related fixes
Sep 2, 2026
c9819e3
Handle failure test case
Sep 2, 2026
85c2647
Merge branch 'main' into fix/textbox-display-whitespace
Sep 4, 2026
5258c55
Handle conflicts
Sep 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ private int ModernPreferredHeight
+ (2 * SystemInformation.FixedFrameBorderSize.Height);
}

return ModernControlVisualStyles.GetPreferredFieldHeight(
SystemVisualSettings settings = Application.SystemVisualSettings;

return ModernControlVisualStyles.GetSingleLineTextBoxPreferredHeight(
fontHeight: FontHeight,
fieldPadding: GetModernFieldPadding(),
borderStyle: BorderStyle.Fixed3D,
focusBorderMetrics: settings.FocusBorderMetrics,
textScaleFactor: settings.TextScaleFactor,
deviceDpi: DeviceDpiInternal);
}
}
Expand Down Expand Up @@ -81,6 +85,7 @@ private unsafe void CaptureNativeComboBaseline(
{
IsCaptured = true,
DeviceDpi = DeviceDpiInternal,
FontHeight = FontHeight,
SelectionFieldItemHeight = selectionFieldItemHeight,
SelectionFieldFrameHeight = Math.Max(
0,
Expand Down Expand Up @@ -169,6 +174,40 @@ private ModernComboTargetState ComputeModernComboTargetState()
{
int topInset = chromeInsets.Top + Padding.Top;
int bottomInset = chromeInsets.Bottom + Padding.Bottom;
int availableTop = ClientRectangle.Top + topInset;
int availableBottom = ClientRectangle.Bottom - bottomInset;

if (DropDownStyle == ComboBoxStyle.DropDown)
{
// Keep the native text-safe height and center the EDIT child instead of putting
// all additional modern field height below its text.
int availableHeight = Math.Max(1, availableBottom - availableTop);
int nativeEditHeight = ScaleNativeBaselineValue(
_nativeComboBaseline.EditBounds.Height);
int baselineFontHeight = ScaleNativeBaselineValue(
_nativeComboBaseline.FontHeight);
int textSafeEditHeight = nativeEditHeight
+ FontHeight
- baselineFontHeight;

editBounds.Height = Math.Max(
1,
Math.Min(textSafeEditHeight, availableHeight));
editBounds.Y = availableTop
+ ((availableHeight - editBounds.Height + 1) / 2);
}
else
{
editBounds.Y += topInset;

// A single-line EDIT control's text visibility depends on its window height.
// Preserve the native height so glyphs are not clipped.
editBounds.Height = Math.Max(
1,
Math.Min(
editBounds.Height,
availableBottom - editBounds.Top));
}

// Inset the edit window horizontally so its rectangular corners clear the rounded
// field arcs, and reserve the (now wider) drop-down button on the button side.
Expand Down Expand Up @@ -676,20 +715,19 @@ private Rectangle GetChildBounds(HWND child)

private Padding GetModernChromeInsets()
{
// Minimal modern field inset plus a small arc-clearance so the flat native edit child's
// rectangular corners are not painted into the rounded-corner arcs. This is chrome padding
// only; the caller still adds the user's Padding on top (see ComputeModernComboTargetState
// and GetModernFieldPadding). It deliberately excludes the classic 3D-border metrics
// (Fixed3DBorderPadding / InternalChromeInset) that the previous implementation inherited
// from the classic field model; the modern field owns a single rounded border across the
// full control, so those insets only produced a spurious inner margin.
int inset = ScaleHelper.ScaleToDpi(
// Keep only horizontal insets for rounded-corner arc clearance. Vertical insets stay zero
// so the native edit child keeps its full text height (important for descenders at 125% DPI).
int horizontalInset = ScaleHelper.ScaleToDpi(
ModernControlVisualStyles.BorderThickness
+ ModernControlVisualStyles.ComboBoxStyleInset
+ ModernControlVisualStyles.ComboBoxFieldArcClearance,
DeviceDpiInternal);

return new Padding(inset);
return new Padding(
left: horizontalInset,
top: 0,
right: horizontalInset,
bottom: 0);
}

private Rectangle GetNativeComboBaselineEditBounds()
Expand All @@ -709,25 +747,36 @@ private int GetModernSimpleListClipRegionApplyCount()

private Padding GetModernFieldPadding()
{
Padding horizontalSource = GetModernChromeInsets();

if (DropDownStyle == ComboBoxStyle.DropDownList)
{
int verticalInset = ScaleHelper.ScaleToDpi(
ModernControlVisualStyles.BorderThickness,
DeviceDpiInternal);

return new Padding(
left: horizontalSource.Left + Padding.Left,
top: verticalInset + Padding.Top,
right: horizontalSource.Right + Padding.Right,
bottom: verticalInset + Padding.Bottom);
}

SystemVisualSettings settings = Application.SystemVisualSettings;

int styleInset = ScaleHelper.ScaleToDpi(
ModernControlVisualStyles.ComboBoxStyleInset,
DeviceDpiInternal);

// Vertical clearance is kept on the classic-derived field model so the modern preferred
// height stays aligned with TextBox (GetPreferredFieldHeight only consumes the vertical
// component). Horizontal clearance uses the minimal modern field inset so the field text
// and drop-down-list caption are not over-inset by classic 3D metrics.
// Editable DropDown / Simple keep the classic-derived vertical model so the native EDIT
// child text metrics remain stable. Horizontal clearance uses minimal modern inset.
Padding verticalSource = ModernControlVisualStyles.GetFieldPadding(
BorderStyle.Fixed3D,
Padding + new Padding(styleInset),
settings.FocusBorderMetrics,
settings.TextScaleFactor,
DeviceDpiInternal);

Padding horizontalSource = GetModernChromeInsets();

return new Padding(
left: horizontalSource.Left + Padding.Left,
top: verticalSource.Top,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,15 +469,11 @@ private static Color GetBorderColor(ComboBox comboBox, bool useAccent)
}

private static int GetBorderThickness(ComboBox comboBox)
{
SystemVisualSettings settings = Application.SystemVisualSettings;
Size borderMetrics = ModernControlVisualStyles.GetFocusBorderMetrics(
settings.FocusBorderMetrics,
settings.TextScaleFactor,
comboBox.DeviceDpiInternal);

return Math.Max(borderMetrics.Width, borderMetrics.Height);
}
=> Math.Max(
1,
ScaleHelper.ScaleToDpi(
ModernControlVisualStyles.BorderThickness,
comboBox.DeviceDpiInternal));

private static GraphicsPath CreateFieldPath(
ComboBox comboBox,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ private readonly struct NativeComboBaseline

public int DeviceDpi { get; init; }

public int FontHeight { get; init; }

public int SelectionFieldItemHeight { get; init; }

public int SelectionFieldFrameHeight { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2979,8 +2979,8 @@ protected override void WndProc(ref Message m)
break;

case PInvokeCore.WM_SETFOCUS:
WmSetFocus();
base.WndProc(ref m);
WmSetFocus();
break;

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,7 @@ public virtual bool Multiline

RecreateHandle();
AdjustHeight(false);
EnsureModernMultilineAutoSizeHeight();
OnMultilineChanged(EventArgs.Empty);
}
}
Expand Down Expand Up @@ -1506,6 +1507,26 @@ private void AdjustHeight(bool returnIfAnchored)
}
}

private void EnsureModernMultilineAutoSizeHeight()
{
if (!_textBoxFlags[s_autoSize]
|| !_textBoxFlags[s_multiline]
|| EffectiveVisualStylesMode < VisualStylesMode.Net11)
{
return;
}

int singleLineHeight = PreferredHeight;

if (Height >= singleLineHeight)
{
return;
}

Height = singleLineHeight;
_requestedHeight = singleLineHeight;
}

/// <summary>
/// Append text to the current text of text box.
/// </summary>
Expand Down Expand Up @@ -1711,6 +1732,7 @@ protected override void OnVisualStylesModeChanged(EventArgs e)
_triggerNewClientSizeRequest = false;
base.OnVisualStylesModeChanged(e);
AdjustHeight(false);
EnsureModernMultilineAutoSizeHeight();
_focusIndicatorRenderer?.Synchronize(Focused, invalidate: false);

RecalculateVisualStylesClientArea();
Expand All @@ -1729,6 +1751,7 @@ protected override void OnSystemVisualSettingsChanged(SystemVisualSettingsChange

CommonProperties.xClearPreferredSizeCache(this);
AdjustHeight(false);
EnsureModernMultilineAutoSizeHeight();
RecalculateVisualStylesClientArea();

if (ParentInternal is { } parent)
Expand Down Expand Up @@ -2510,6 +2533,57 @@ private unsafe void WmNcCalcSize(ref Message m)

ref RECT clientRect = ref ncCalcSizeParams->rgrc._0;

if (!Multiline)
{
// Keep enough single-line client height for native edit text metrics when the modern
// chrome carve would otherwise leave too little room at higher DPI scales.
int clientHeight = clientRect.bottom - clientRect.top;
int minimumSingleLineClientHeight = FontHeight + ScaleVisualStylesMetric(3);
int maxVerticalCarve = Math.Max(0, clientHeight - minimumSingleLineClientHeight);

if (padding.Vertical > maxVerticalCarve)
{
int overflow = padding.Vertical - maxVerticalCarve;
int minimumTopPadding = BorderStyle switch
{
BorderStyle.None => 0,
BorderStyle.FixedSingle => ScaleVisualStylesMetric(ModernControlVisualStyles.BorderThickness),
_ => ScaleVisualStylesMetric(ModernControlVisualStyles.InternalChromeInset + ModernControlVisualStyles.BorderThickness)
};
int minimumBottomPadding = BorderStyle == BorderStyle.None
? 0
: ScaleVisualStylesMetric(ModernControlVisualStyles.BorderThickness);

// Bias the recovery toward the bottom inset first so baseline-driven single-line
// text sits slightly lower, while still preserving the minimum client height.
int availableBottomReduction = Math.Max(0, padding.Bottom - minimumBottomPadding);
int bottomReduction = Math.Min(overflow, availableBottomReduction);
padding.Bottom -= bottomReduction;
overflow -= bottomReduction;

int availableTopReduction = Math.Max(0, padding.Top - minimumTopPadding);
int topReduction = Math.Min(overflow, availableTopReduction);
padding.Top -= topReduction;
overflow -= topReduction;

if (overflow > 0)
{
int minimumVisibleVerticalPadding = BorderStyle == BorderStyle.None
? 0
: ScaleVisualStylesMetric(ModernControlVisualStyles.BorderThickness);

int availableBottomVisualReduction = Math.Max(0, padding.Bottom - minimumVisibleVerticalPadding);
bottomReduction = Math.Min(overflow, availableBottomVisualReduction);
padding.Bottom -= bottomReduction;
overflow -= bottomReduction;

int availableTopVisualReduction = Math.Max(0, padding.Top - minimumVisibleVerticalPadding);
topReduction = Math.Min(overflow, availableTopVisualReduction);
padding.Top -= topReduction;
}
}
}

// Never-invert clamp: a large Padding plus the live scrollbar allowance can drive the
// carved client rect to zero or inverted. A 0-1px client area is acceptable and intended
// (shipping multiline TextBox already collapses this way); we only prevent underflow past
Expand Down Expand Up @@ -2660,7 +2734,7 @@ private protected virtual void OnNcPaint(Graphics graphics, HDC windowHdc)
{
int cornerRadius = ScaleVisualStylesMetric(ModernControlVisualStyles.FieldCornerRadius);
Size focusBorderMetrics = GetVisualStylesFocusBorderMetrics();
int borderThickness = Math.Max(focusBorderMetrics.Width, focusBorderMetrics.Height);
int borderThickness = ScaleVisualStylesMetric(ModernControlVisualStyles.BorderThickness);
int focusBandHeight = GetVisualStylesFocusBandHeight();

Color clientBackColor = BackColor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ internal partial class UpDownButtons : Control
private Bitmap? _cachedBitmap;

private bool _doubleClickFired;
private const double ModernArrowScaleFactor = 0.8;

/// <summary>
/// Initializes a new instance of the <see cref="UpDownButtons"/> class.
Expand Down Expand Up @@ -319,14 +320,16 @@ protected override void OnPaint(PaintEventArgs e)
GetButtonRectangle(ButtonID.Down),
ModernControlButtonStyle.Down,
GetButtonState(ButtonID.Down),
isDarkMode);
isDarkMode,
ModernArrowScaleFactor);

DrawModernControlButton(
cachedGraphics,
GetButtonRectangle(ButtonID.Up),
ModernControlButtonStyle.Up,
GetButtonState(ButtonID.Up),
isDarkMode);
isDarkMode,
ModernArrowScaleFactor);

e.GraphicsInternal.DrawImageUnscaled(_cachedBitmap, new Point(0, 0));

Expand Down Expand Up @@ -358,7 +361,8 @@ protected override void OnPaint(PaintEventArgs e)
? ModernControlButtonState.Pressed
: (Enabled ? (_mouseOver == ButtonID.Up ? ModernControlButtonState.Hover : ModernControlButtonState.Normal)
: ModernControlButtonState.Disabled),
true);
true,
ModernArrowScaleFactor);

DrawModernControlButton(
cachedGraphics,
Expand All @@ -368,7 +372,8 @@ protected override void OnPaint(PaintEventArgs e)
? ModernControlButtonState.Pressed
: (Enabled ? (_mouseOver == ButtonID.Down ? ModernControlButtonState.Hover : ModernControlButtonState.Normal)
: ModernControlButtonState.Disabled),
true);
true,
ModernArrowScaleFactor);

e.GraphicsInternal.DrawImageUnscaled(
_cachedBitmap,
Expand Down
Loading