diff --git a/src/System.Windows.Forms/System/Windows/Forms/Control.cs b/src/System.Windows.Forms/System/Windows/Forms/Control.cs index 82efce46fce..14d589bbab4 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Control.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Control.cs @@ -162,6 +162,7 @@ public unsafe partial class Control : internal const string ExplorerThemeIdentifier = "Explorer"; internal const string ItemsViewThemeIdentifier = "ItemsView"; internal const string ComboBoxButtonThemeIdentifier = "CFD"; + internal const string BannerContainerThemeIdentifier = "FileExplorerBannerContainer"; private const short PaintLayerBackground = 1; private const short PaintLayerForeground = 2; @@ -9148,9 +9149,12 @@ internal virtual void RecreateHandleCore() bool focused = ContainsFocus; - Debug.WriteLineIf(CoreSwitches.PerfTrack.Enabled, $"RecreateHandle: {GetType().FullName} [Text={Text}]"); + Debug.WriteLineIf( + CoreSwitches.PerfTrack.Enabled, + $"RecreateHandle: {GetType().FullName} [Text={Text}]"); bool created = GetState(States.Created); + if (GetState(States.TrackingMouseEvent)) { SetState(States.MouseEnterPending, true); @@ -9173,9 +9177,11 @@ internal virtual void RecreateHandleCore() if (ChildControls is { } children && children.Count > 0) { controlSnapshot = new Control[children.Count]; + for (int i = 0; i < children.Count; i++) { Control childControl = children[i]; + if (childControl is not null && childControl.IsHandleCreated) { // SetParent to parking window @@ -9235,6 +9241,7 @@ internal virtual void RecreateHandleCore() for (int i = 0; i < controlSnapshot.Length; i++) { Control? childControl = controlSnapshot[i]; + if (childControl is not null && childControl.IsHandleCreated) { // Re-parent the control. diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/TabControl/TabControl.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/TabControl/TabControl.cs index 57addb6d0eb..dfa77ba121d 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/TabControl/TabControl.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/TabControl/TabControl.cs @@ -72,6 +72,7 @@ public partial class TabControl : Control private bool _skipUpdateSize; private ToolTipBuffer _toolTipBuffer; + private bool _suspendDarkModeChange; /// /// Constructs a TabBase object, usually as the base class for a TabStrip or TabControl. @@ -157,7 +158,10 @@ public TabAppearance Appearance SourceGenerated.EnumValidator.Validate(value); _appearance = value; + + _suspendDarkModeChange = true; RecreateHandle(); + ApplyDarkModeOnDemand(); // Fire OnStyleChanged(EventArgs.Empty) here since we are no longer calling UpdateStyles( ) but always reCreating the Handle. OnStyleChanged(EventArgs.Empty); @@ -1244,6 +1248,7 @@ protected override void OnHandleCreated(EventArgs e) base.OnHandleCreated(e); _cachedDisplayRect = Rectangle.Empty; ApplyItemSize(); + if (_imageList is not null) { PInvokeCore.SendMessage(this, PInvoke.TCM_SETIMAGELIST, 0, _imageList.Handle); @@ -1289,7 +1294,22 @@ protected override void OnHandleCreated(EventArgs e) } UpdateTabSelection(false); + ApplyDarkModeOnDemand(); + } + +#pragma warning disable WFO5001 + private void ApplyDarkModeOnDemand() + { + // We need to avoid to apply the DarkMode theme twice on handle recreate. + if (!_suspendDarkModeChange && Application.IsDarkModeEnabled) + { + PInvoke.SetWindowTheme(HWND, null, $"{DarkModeIdentifier}::{BannerContainerThemeIdentifier}"); + PInvokeCore.EnumChildWindows(this, StyleChildren); + } + + _suspendDarkModeChange = false; } +#pragma warning restore WFO5001 protected override void OnHandleDestroyed(EventArgs e) { @@ -1771,6 +1791,10 @@ private bool ShouldSerializeItemSize() return !_padding.Equals(s_defaultPaddingPoint); } + private BOOL StyleChildren(HWND handle) => + PInvoke.SetWindowTheme(handle, $"{DarkModeIdentifier}_{ExplorerThemeIdentifier}", null) + .Succeeded; + /// /// Returns a string representation for this control. /// @@ -1808,6 +1832,7 @@ protected void UpdateTabSelection(bool updateFocus) // make current panel invisible TabPage[] tabPages = GetTabPages(); + if (index != -1) { // Changing the bounds of the TabPage during scaling @@ -1889,6 +1914,7 @@ protected override void OnStyleChanged(EventArgs e) { base.OnStyleChanged(e); _cachedDisplayRect = Rectangle.Empty; + UpdateTabSelection(false); }