Skip to content

Commit ef1cdc3

Browse files
willibrandonKlausLoeffelmann
authored andcommitted
Darken TabControl in dark mode
1 parent 94ef520 commit ef1cdc3

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/System.Windows.Forms/System/Windows/Forms/Control.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ public unsafe partial class Control :
162162
internal const string ExplorerThemeIdentifier = "Explorer";
163163
internal const string ItemsViewThemeIdentifier = "ItemsView";
164164
internal const string ComboBoxButtonThemeIdentifier = "CFD";
165+
internal const string BannerContainerThemeIdentifier = "FileExplorerBannerContainer";
165166

166167
private const short PaintLayerBackground = 1;
167168
private const short PaintLayerForeground = 2;
@@ -9207,9 +9208,12 @@ internal virtual void RecreateHandleCore()
92079208

92089209
bool focused = ContainsFocus;
92099210

9210-
Debug.WriteLineIf(CoreSwitches.PerfTrack.Enabled, $"RecreateHandle: {GetType().FullName} [Text={Text}]");
9211+
Debug.WriteLineIf(
9212+
CoreSwitches.PerfTrack.Enabled,
9213+
$"RecreateHandle: {GetType().FullName} [Text={Text}]");
92119214

92129215
bool created = GetState(States.Created);
9216+
92139217
if (GetState(States.TrackingMouseEvent))
92149218
{
92159219
SetState(States.MouseEnterPending, true);
@@ -9232,9 +9236,11 @@ internal virtual void RecreateHandleCore()
92329236
if (ChildControls is { } children && children.Count > 0)
92339237
{
92349238
controlSnapshot = new Control[children.Count];
9239+
92359240
for (int i = 0; i < children.Count; i++)
92369241
{
92379242
Control childControl = children[i];
9243+
92389244
if (childControl is not null && childControl.IsHandleCreated)
92399245
{
92409246
// SetParent to parking window
@@ -9294,6 +9300,7 @@ internal virtual void RecreateHandleCore()
92949300
for (int i = 0; i < controlSnapshot.Length; i++)
92959301
{
92969302
Control? childControl = controlSnapshot[i];
9303+
92979304
if (childControl is not null && childControl.IsHandleCreated)
92989305
{
92999306
// Re-parent the control.

src/System.Windows.Forms/System/Windows/Forms/Controls/TabControl/TabControl.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public partial class TabControl : Control
7272
private bool _skipUpdateSize;
7373

7474
private ToolTipBuffer _toolTipBuffer;
75+
private bool _suspendDarkModeChange;
7576

7677
/// <summary>
7778
/// Constructs a TabBase object, usually as the base class for a TabStrip or TabControl.
@@ -154,7 +155,10 @@ public TabAppearance Appearance
154155
SourceGenerated.EnumValidator.Validate(value);
155156

156157
_appearance = value;
158+
159+
_suspendDarkModeChange = true;
157160
RecreateHandle();
161+
ApplyDarkModeOnDemand();
158162

159163
// Fire OnStyleChanged(EventArgs.Empty) here since we are no longer calling UpdateStyles( ) but always reCreating the Handle.
160164
OnStyleChanged(EventArgs.Empty);
@@ -1245,6 +1249,7 @@ protected override void OnHandleCreated(EventArgs e)
12451249
base.OnHandleCreated(e);
12461250
_cachedDisplayRect = Rectangle.Empty;
12471251
ApplyItemSize();
1252+
12481253
if (_imageList is not null)
12491254
{
12501255
PInvokeCore.SendMessage(this, PInvoke.TCM_SETIMAGELIST, 0, _imageList.Handle);
@@ -1290,7 +1295,22 @@ protected override void OnHandleCreated(EventArgs e)
12901295
}
12911296

12921297
UpdateTabSelection(false);
1298+
ApplyDarkModeOnDemand();
1299+
}
1300+
1301+
#pragma warning disable WFO5001
1302+
private void ApplyDarkModeOnDemand()
1303+
{
1304+
// We need to avoid to apply the DarkMode theme twice on handle recreate.
1305+
if (!_suspendDarkModeChange && Application.IsDarkModeEnabled)
1306+
{
1307+
PInvoke.SetWindowTheme(HWND, null, $"{DarkModeIdentifier}::{BannerContainerThemeIdentifier}");
1308+
PInvokeCore.EnumChildWindows(this, StyleChildren);
1309+
}
1310+
1311+
_suspendDarkModeChange = false;
12931312
}
1313+
#pragma warning restore WFO5001
12941314

12951315
protected override void OnHandleDestroyed(EventArgs e)
12961316
{
@@ -1554,6 +1574,8 @@ internal override void RecreateHandleCore()
15541574
TabPages.Add(tabPages[i]);
15551575
}
15561576

1577+
ApplyDarkModeOnDemand();
1578+
15571579
try
15581580
{
15591581
SetState(State.FromCreateHandles, true);
@@ -1772,6 +1794,10 @@ private bool ShouldSerializeItemSize()
17721794
return !_padding.Equals(s_defaultPaddingPoint);
17731795
}
17741796

1797+
private BOOL StyleChildren(HWND handle) =>
1798+
PInvoke.SetWindowTheme(handle, $"{DarkModeIdentifier}_{ExplorerThemeIdentifier}", null)
1799+
.Succeeded;
1800+
17751801
/// <summary>
17761802
/// Returns a string representation for this control.
17771803
/// </summary>
@@ -1809,6 +1835,7 @@ protected void UpdateTabSelection(bool updateFocus)
18091835

18101836
// make current panel invisible
18111837
TabPage[] tabPages = GetTabPages();
1838+
18121839
if (index != -1)
18131840
{
18141841
// Changing the bounds of the TabPage during scaling
@@ -1890,6 +1917,7 @@ protected override void OnStyleChanged(EventArgs e)
18901917
{
18911918
base.OnStyleChanged(e);
18921919
_cachedDisplayRect = Rectangle.Empty;
1920+
18931921
UpdateTabSelection(false);
18941922
}
18951923

0 commit comments

Comments
 (0)