diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/ContainerControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/ContainerControl.cs
index a13540a8153..0f869f200df 100644
--- a/src/System.Windows.Forms/src/System/Windows/Forms/ContainerControl.cs
+++ b/src/System.Windows.Forms/src/System/Windows/Forms/ContainerControl.cs
@@ -48,6 +48,11 @@ public class ContainerControl : ScrollableControl, IContainerControl
///
private bool _isScaledByDpiChangedEvent;
+ ///
+ /// Indicates scaling, due to DPI changed event, of the container control is in progress.
+ ///
+ internal bool _dpiScalingInProgress;
+
private BitVector32 _state;
///
@@ -1441,6 +1446,8 @@ internal void ScaleContainerForDpi(int deviceDpiNew, int deviceDpiOld, Rectangle
SuspendAllLayout(this);
try
{
+ _dpiScalingInProgress = true;
+
if (LocalAppContextSwitches.ScaleTopLevelFormMinMaxSizeForDpi)
{
// The suggested rectangle comes from Windows, and it does not match with our calculations for scaling controls by AutoscaleFactor.
@@ -1491,6 +1498,9 @@ internal void ScaleContainerForDpi(int deviceDpiNew, int deviceDpiOld, Rectangle
// We want to perform layout for dpi-changed high Dpi improvements - setting the second parameter to 'true'
ResumeAllLayout(this, true);
_isScaledByDpiChangedEvent = false;
+
+ // Scaling and ResumeLayout, due to DPI changed event, should be finished by now for this container.
+ _dpiScalingInProgress = false;
}
}
diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs
index e775a900808..218177a9726 100644
--- a/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs
+++ b/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs
@@ -1713,10 +1713,10 @@ internal bool IsTopMdiWindowClosing
}
///
- /// returns bool indicating whether the control is currently being scaled.
+ /// Returns bool indicating whether the control is currently being scaled.
/// This property is set in ScaleControl method to allow method being called to condition code that should not run for scaling.
///
- internal bool IsCurrentlyBeingScaled
+ internal bool ScalingInProgress
{
get => GetExtendedState(ExtendedStates.CurrentlyBeingScaled);
private set => SetExtendedState(ExtendedStates.CurrentlyBeingScaled, value);
@@ -10450,7 +10450,7 @@ internal void ScaleControl(SizeF includedFactor, SizeF excludedFactor, Control r
{
try
{
- IsCurrentlyBeingScaled = true;
+ ScalingInProgress = true;
BoundsSpecified includedSpecified = BoundsSpecified.None;
BoundsSpecified excludedSpecified = BoundsSpecified.None;
@@ -10489,7 +10489,7 @@ internal void ScaleControl(SizeF includedFactor, SizeF excludedFactor, Control r
}
finally
{
- IsCurrentlyBeingScaled = false;
+ ScalingInProgress = false;
}
}
@@ -10589,9 +10589,6 @@ protected virtual void ScaleControl(SizeF factor, BoundsSpecified specified)
scaledSize = LayoutUtils.UnionSizes(scaledSize, minSize);
if (DpiHelper.IsScalingRequirementMet
- // In the v2 layout, anchors are updated/computed after the controls bounds changed
- // and, thus, don't need scaling.
- && !DefaultLayout.UseAnchorLayoutV2(this)
&& ParentInternal is { } parent
&& (parent.LayoutEngine == DefaultLayout.Instance))
{
diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Layout/DefaultLayout.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Layout/DefaultLayout.cs
index d443d5e939a..57652becf62 100644
--- a/src/System.Windows.Forms/src/System/Windows/Forms/Layout/DefaultLayout.cs
+++ b/src/System.Windows.Forms/src/System/Windows/Forms/Layout/DefaultLayout.cs
@@ -896,6 +896,12 @@ internal static void UpdateAnchorInfoV2(Control control)
return;
}
+ // Anchors are already scaled for the new DPI.
+ if (DpiScalingInProgress(control, parent))
+ {
+ return;
+ }
+
AnchorInfo anchorInfo = GetAnchorInfo(control);
if (anchorInfo is null)
{
@@ -913,6 +919,28 @@ internal static void UpdateAnchorInfoV2(Control control)
anchorInfo.Right = displayRect.Width - (x + elementBounds.Width);
anchorInfo.Bottom = displayRect.Height - (y + elementBounds.Height);
+
+ // Walk through parent hierarchy and check if scaling due to DPI change is in progress.
+ static bool DpiScalingInProgress(Control control, Control parent)
+ {
+ if (control.ScalingInProgress
+ || (control is ContainerControl container && container._dpiScalingInProgress))
+ {
+ return true;
+ }
+
+ while (parent is not null)
+ {
+ if (parent is ContainerControl parentContainer && parentContainer._dpiScalingInProgress)
+ {
+ return true;
+ }
+
+ parent = parent.Parent;
+ }
+
+ return false;
+ }
}
public static AnchorStyles GetAnchor(IArrangedElement element) => CommonProperties.xGetAnchor(element);
diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs
index af97449b594..b624f03b7ff 100644
--- a/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs
+++ b/src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.cs
@@ -1756,7 +1756,7 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound
// Second argument to GetPreferredWidth and GetPreferredHeight is a boolean specifying if we should update the number of rows/columns.
// We only want to update the number of rows/columns if we are not currently being scaled.
- bool updateRowsAndColumns = !DpiHelper.IsScalingRequirementMet || !IsCurrentlyBeingScaled;
+ bool updateRowsAndColumns = !DpiHelper.IsScalingRequirementMet || !ScalingInProgress;
if (width != oldBounds.Width)
{