Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 24 additions & 3 deletions src/System.Windows.Forms/System/Windows/Forms/Control.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ public unsafe partial class Control :

internal byte LayoutSuspendCount { get; private set; }

// Flag for the youngest control in the descendant-inheritance hierarchy as the
// ultimate truth if the control - by having set the ControlStyles. -
// indicates to participate in automatic dark mode theming or not.
internal bool? _darkModeRequestState;

/// <summary>
/// Initializes a new instance of the <see cref="Control"/> class.
/// </summary>
Expand Down Expand Up @@ -7379,7 +7384,7 @@ protected virtual void OnHandleCreated(EventArgs e)

#pragma warning disable WFO5001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
if (Application.IsDarkModeEnabled
&& GetStyle(ControlStyles.ApplyThemingImplicitly)
&& _darkModeRequestState is true
&& !RecreatingHandle)
{
_ = PInvoke.SetWindowTheme(
Expand Down Expand Up @@ -9344,7 +9349,7 @@ internal virtual void RecreateHandleCore()
// ensure that the theming is applied to all child controls as well.
#pragma warning disable WFO5001
if (Application.IsDarkModeEnabled
&& GetStyle(ControlStyles.ApplyThemingImplicitly))
&& _darkModeRequestState is true)
{
_ = PInvoke.SetWindowTheme(
hwnd: HWND,
Expand Down Expand Up @@ -10325,12 +10330,27 @@ private protected void SetExtendedState(ExtendedStates flag, bool value)
/// NOTE: This is control style, not the Win32 style of the hWnd.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Advanced)]
#pragma warning disable WFO5001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
protected void SetStyle(ControlStyles flag, bool value)
{
// WARNING: if we ever add argument checking to "flag", we will need
// to move private styles like Layered to State.
_controlStyle = value ? _controlStyle | flag : _controlStyle & ~flag;

// We need to special-treat ApplyThemingImplicitly, as it is not a real style,which we
// would hand down to Win32. It's important, that we capture what an inherited control
// wanted in terms of getting the respective dark mode theme applied automatically.
// Since the inherited control sets or clears this style implicitly in CreateParams
// (Which always runs _before_ its constructor code runs), and since base controls can
// reset those settings - the source of truth ultimately is the value which gets set
// for the first time a control sets or clears this style explicitly in CreateParams.
if ((flag & ControlStyles.ApplyThemingImplicitly) == ControlStyles.ApplyThemingImplicitly
&& !_darkModeRequestState.HasValue)
{
_darkModeRequestState = value;
}
}
#pragma warning restore WFO5001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

internal virtual void SetToolTip(ToolTip toolTip)
{
Expand Down Expand Up @@ -10391,7 +10411,8 @@ protected virtual void SetVisibleCore(bool value)
{
// We shouldn't mess with the color mode if users haven't specifically set it.
// https://github.com/dotnet/winforms/issues/12014
if (value && Application.ColorModeSet)
// And we shouldn't prepare dark mode, if the form opted out.
if (value && Application.ColorModeSet && _darkModeRequestState is true)
{
PrepareDarkMode(HWND, Application.IsDarkModeEnabled);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ private protected override bool OwnerDraw
&& Image is null

// ...the user wants to opt out of implicit DarkMode rendering.
&& GetStyle(ControlStyles.ApplyThemingImplicitly)
&& _darkModeRequestState is true

// And all of this only counts for FlatStyle.Standard. For the
// rest, we're using specific renderers anyway, which check
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4673,7 +4673,7 @@ protected override void OnHandleCreated(EventArgs e)
private void ApplyDarkModeOnDemand()
{
if (Application.IsDarkModeEnabled
&& GetStyle(ControlStyles.ApplyThemingImplicitly))
&& _darkModeRequestState is true)
{
// Enable double buffering when in dark mode to reduce flicker.
uint exMask = PInvoke.LVS_EX_ONECLICKACTIVATE | PInvoke.LVS_EX_TWOCLICKACTIVATE |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ public override Color BackColor

// If we're ReadOnly and in DarkMode, we are using a different background color.
? Application.IsDarkModeEnabled
&& GetStyle(ControlStyles.ApplyThemingImplicitly)
&& _darkModeRequestState is true
? SystemColors.ControlDarkDark
: SystemColors.Control
: SystemColors.Window;
Expand Down Expand Up @@ -955,7 +955,7 @@ private void EnsureReadonlyBackgroundColor(bool value)
{
// If we have no specifically defined back color, we set the back color in case we're in dark mode.
if (Application.IsDarkModeEnabled
&& GetStyle(ControlStyles.ApplyThemingImplicitly))
&& _darkModeRequestState is true)
{
base.BackColor = value ? SystemColors.ControlLight : SystemColors.Window;
Invalidate();
Expand Down