diff --git a/src/System.Windows.Forms.Primitives/src/System/LocalAppContextSwitches/LocalAppContextSwitches.cs b/src/System.Windows.Forms.Primitives/src/System/LocalAppContextSwitches/LocalAppContextSwitches.cs index 5b728b3472a..0e71a335aaa 100644 --- a/src/System.Windows.Forms.Primitives/src/System/LocalAppContextSwitches/LocalAppContextSwitches.cs +++ b/src/System.Windows.Forms.Primitives/src/System/LocalAppContextSwitches/LocalAppContextSwitches.cs @@ -26,6 +26,7 @@ internal static partial class LocalAppContextSwitches internal const string EnableMsoComponentManagerSwitchName = "Switch.System.Windows.Forms.EnableMsoComponentManager"; internal const string TreeNodeCollectionAddRangeRespectsSortOrderSwitchName = "System.Windows.Forms.TreeNodeCollectionAddRangeRespectsSortOrder"; internal const string MoveTreeViewTextLocationOnePixelSwitchName = "System.Windows.Forms.TreeView.MoveTreeViewTextLocationOnePixel"; + internal const string MirrorTopMostForModalDialogsSwitchName = "System.Windows.Forms.MirrorTopMostForModalDialogs"; private static int s_scaleTopLevelFormMinMaxSizeForDpi; private static int s_anchorLayoutV2; @@ -37,6 +38,7 @@ internal static partial class LocalAppContextSwitches private static int s_noClientNotifications; private static int s_enableMsoComponentManager; private static int s_treeNodeCollectionAddRangeRespectsSortOrder; + private static int s_mirrorTopMostForModalDialogs; private static int s_moveTreeViewTextLocationOnePixel; @@ -222,6 +224,18 @@ public static bool TreeNodeCollectionAddRangeRespectsSortOrder get => GetCachedSwitchValue(TreeNodeCollectionAddRangeRespectsSortOrderSwitchName, ref s_treeNodeCollectionAddRangeRespectsSortOrder); } + /// + /// When true, ShowDialog will temporarily set the dialog as TopMost if its owner is TopMost. + /// This prevents the dialog from being covered by the owner during the modal session. + /// The original TopMost state is restored after closing. + /// Default is false. Set to true for .NET Framework-compatible behavior. + /// + public static bool MirrorTopMostForModalDialogs + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => GetCachedSwitchValue(MirrorTopMostForModalDialogsSwitchName, ref s_mirrorTopMostForModalDialogs); + } + /// /// Indicates whether to move the text position of a TreeView node one pixel /// to the right relative to the upper-left corner of the TreeView control. diff --git a/src/System.Windows.Forms/System/Windows/Forms/Form.cs b/src/System.Windows.Forms/System/Windows/Forms/Form.cs index c3900d09c6b..be78adab8f0 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Form.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Form.cs @@ -5718,6 +5718,9 @@ public DialogResult ShowDialog(IWin32Window? owner) Form? oldOwner = OwnerInternal; + bool originalTopMost = TopMost; + bool mirrored = false; + try { SetState(States.Modal, true); @@ -5755,6 +5758,12 @@ public DialogResult ShowDialog(IWin32Window? owner) if (owner is Form form && owner != oldOwner) { Owner = form; + + if (AppContextSwitches.MirrorTopMostForModalDialogs && TopLevel && !IsMdiChild && Owner.TopMost && !TopMost) + { + TopMost = true; + mirrored = true; + } } else { @@ -5814,6 +5823,11 @@ public DialogResult ShowDialog(IWin32Window? owner) Owner = oldOwner; Properties.RemoveValue(s_propDialogOwner); GC.KeepAlive(ownerHwnd.Wrapper); + + if (mirrored) + { + TopMost = originalTopMost; + } } return DialogResult;