Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Dark Mode Visual Style Theme Subclass #11985

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions src/System.Windows.Forms/src/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3320,6 +3320,7 @@ static System.Windows.Forms.VisualStyles.VisualStyleInformation.Url.get -> strin
static System.Windows.Forms.VisualStyles.VisualStyleInformation.Version.get -> string!
static System.Windows.Forms.VisualStyles.VisualStyleRenderer.IsElementDefined(System.Windows.Forms.VisualStyles.VisualStyleElement! element) -> bool
static System.Windows.Forms.VisualStyles.VisualStyleRenderer.IsSupported.get -> bool
static System.Windows.Forms.VisualStyles.VisualStyleRenderer.IsDarkModeSupported.get -> bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot take new APIs at this point. So, this needs to be reverted.

static System.Windows.Forms.WindowsFormsSynchronizationContext.AutoInstall.get -> bool
static System.Windows.Forms.WindowsFormsSynchronizationContext.AutoInstall.set -> void
static System.Windows.Forms.WindowsFormsSynchronizationContext.Uninstall() -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ public sealed partial class Application
private static SystemColorMode? s_colorMode;
#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.

private const string DarkModeKeyPath = "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
private const string DarkModeKey = "AppsUseLightTheme";
private const int SystemDarkModeDisabled = 1;

/// <summary>
Expand Down Expand Up @@ -379,21 +377,9 @@ private static int GetSystemColorModeInternal()
return SystemDarkModeDisabled;
}

int systemColorMode = SystemDarkModeDisabled;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're still discussing, if we can take this for .NET 9 RC2 (the bar is service, and we would need to consider this a bug fix). So, this particular change, we would probably not want to take. @merriemcgaw, @lonitra.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be as it is, please revert this.


try
{
// 0 for dark mode and |1| for light mode.
systemColorMode = Math.Abs((Registry.GetValue(
keyName: DarkModeKeyPath,
valueName: DarkModeKey,
defaultValue: SystemDarkModeDisabled) as int?) ?? systemColorMode);
}
catch (Exception ex) when (!ex.IsCriticalException())
{
}

return systemColorMode;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here - we need to keep this.

#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.
return VisualStyleRenderer.IsDarkModeSupported ? 0 : 1;
#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.
}

private static bool IsSystemDarkModeAvailable =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ 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";
internal const string NavPaneThemeIdentifier = "ExplorerNavPane";
private const short PaintLayerBackground = 1;
private const short PaintLayerForeground = 2;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ public static class ComboBoxRenderer
// Make this per-thread, so that different threads can safely use these methods.
[ThreadStatic]
private static VisualStyleRenderer? t_visualStyleRenderer;
private static readonly VisualStyleElement s_comboBoxElement = VisualStyleElement.ComboBox.DropDownButton.Normal;
#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.
private static readonly VisualStyleElement s_comboBoxElement = Application.IsDarkModeEnabled
? VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ComboBoxButtonThemeIdentifier}::COMBOBOX", 1, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you introduce a const for COMBOBOX as well?

: VisualStyleElement.ComboBox.DropDownButton.Normal;
#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.
private static readonly VisualStyleElement s_textBoxElement = VisualStyleElement.TextBox.TextEdit.Normal;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ public partial class DataGridViewButtonCell : DataGridViewCell
private static readonly int s_propButtonCellFlatStyle = PropertyStore.CreateKey();
private static readonly int s_propButtonCellState = PropertyStore.CreateKey();
private static readonly int s_propButtonCellUseColumnTextForButtonValue = PropertyStore.CreateKey();
private static readonly VisualStyleElement s_buttonElement = VisualStyleElement.Button.PushButton.Normal;
#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.
private static readonly VisualStyleElement s_darkButtonElement = VisualStyleElement.CreateElement("DarkMode_Explorer::BUTTON", 1, 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, instead of hardcoding "DarkMode_Explorer" it should be an interpolated const, e.g.: {DarkModeIdentifier}_{Explorer}.
See:

internal const string DarkModeIdentifier = "DarkMode";
internal const string ExplorerThemeIdentifier = "Explorer";
internal const string ItemsViewThemeIdentifier = "ItemsView";
internal const string ComboBoxButtonThemeIdentifier = "CFD";

If any more consts need adding - they should be added here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, does that look good now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I do not see that you changed anything.
Can you make the changes?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this was missed

Suggested change
private static readonly VisualStyleElement s_darkButtonElement = VisualStyleElement.CreateElement("DarkMode_Explorer::BUTTON", 1, 1);
private static readonly VisualStyleElement s_darkButtonElement = VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ExplorerThemeIdentifier}::BUTTON", 1, 1);

private static readonly VisualStyleElement s_lightButtonElement = VisualStyleElement.Button.PushButton.Normal;
private static readonly VisualStyleElement s_buttonElement = Application.IsDarkModeEnabled ? s_darkButtonElement : s_lightButtonElement;
#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.

private const byte DATAGRIDVIEWBUTTONCELL_themeMargin = 100; // Used to calculate the margins required for theming rendering
private const byte DATAGRIDVIEWBUTTONCELL_horizontalTextMargin = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@ public partial class DataGridViewCheckBoxCell : DataGridViewCell, IDataGridViewE
private const DataGridViewContentAlignment AnyBottom = DataGridViewContentAlignment.BottomRight | DataGridViewContentAlignment.BottomCenter | DataGridViewContentAlignment.BottomLeft;
private const DataGridViewContentAlignment AnyMiddle = DataGridViewContentAlignment.MiddleRight | DataGridViewContentAlignment.MiddleCenter | DataGridViewContentAlignment.MiddleLeft;

private static readonly VisualStyleElement s_checkBoxElement = VisualStyleElement.Button.CheckBox.UncheckedNormal;
#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.
private static readonly VisualStyleElement s_darkCheckBoxElement = VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ExplorerThemeIdentifier}::BUTTON", 3, 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you introduce a const for the button part as well?

private static readonly VisualStyleElement s_lightCheckBoxElement = VisualStyleElement.Button.CheckBox.UncheckedNormal;
private static readonly VisualStyleElement s_checkBoxElement = Application.IsDarkModeEnabled
? s_darkCheckBoxElement
: s_lightCheckBoxElement;
#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.

private static readonly int s_propButtonCellState = PropertyStore.CreateKey();
private static readonly int s_propTrueValue = PropertyStore.CreateKey();
private static readonly int s_propFalseValue = PropertyStore.CreateKey();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ public static VisualStyleRenderer VisualStyleRenderer
{
get
{
s_visualStyleRenderer ??= new VisualStyleRenderer(s_headerElement);
#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.
s_visualStyleRenderer ??= new VisualStyleRenderer(Application.IsDarkModeEnabled
? VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ItemsViewThemeIdentifier}::Header", 1, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you introduce a const for the Header part as well?

: VisualStyleElement.Header.Item.Normal);
#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.

return s_visualStyleRenderer;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ namespace System.Windows.Forms;

public partial class DataGridViewColumnHeaderCell : DataGridViewHeaderCell
{
private static readonly VisualStyleElement s_headerElement = VisualStyleElement.Header.Item.Normal;
#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.
private static readonly VisualStyleElement s_headerElement = Application.IsDarkModeEnabled
? VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ItemsViewThemeIdentifier}::Header", 1, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here?

: VisualStyleElement.Header.Item.Normal;
#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.

private const byte SortGlyphSeparatorWidth = 2; // additional 2 pixels between caption and glyph
private const byte SortGlyphHorizontalMargin = 4; // 4 pixels on left & right of glyph
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,29 @@ private static class DataGridViewComboBoxCellRenderer
{
[ThreadStatic]
private static VisualStyleRenderer? t_visualStyleRenderer;
private static readonly VisualStyleElement s_comboBoxBorder = VisualStyleElement.ComboBox.Border.Normal;
private static readonly VisualStyleElement s_comboBoxDropDownButtonRight = VisualStyleElement.ComboBox.DropDownButtonRight.Normal;
private static readonly VisualStyleElement s_comboBoxDropDownButtonLeft = VisualStyleElement.ComboBox.DropDownButtonLeft.Normal;
private static readonly VisualStyleElement s_comboBoxReadOnlyButton = VisualStyleElement.ComboBox.ReadOnlyButton.Normal;
#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.
private static readonly VisualStyleElement s_comboBoxBorder = Application.IsDarkModeEnabled
? VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ComboBoxButtonThemeIdentifier}::COMBOBOX", 4, 1)
: VisualStyleElement.ComboBox.Border.Normal;
#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.

#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.
private static readonly VisualStyleElement s_comboBoxDropDownButtonRight = Application.IsDarkModeEnabled
? VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ComboBoxButtonThemeIdentifier}::COMBOBOX", 6, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you address the Combox text as well (both spots)? Thanks!

: VisualStyleElement.ComboBox.DropDownButtonRight.Normal;
#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.

#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.
private static readonly VisualStyleElement s_comboBoxDropDownButtonLeft = Application.IsDarkModeEnabled
? VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ComboBoxButtonThemeIdentifier}::COMBOBOX", 7, 1)
: VisualStyleElement.ComboBox.DropDownButtonLeft.Normal;
#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.

#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.
private static readonly VisualStyleElement s_comboBoxReadOnlyButton = Application.IsDarkModeEnabled
? VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ComboBoxButtonThemeIdentifier}::COMBOBOX", 5, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here! 😸

: VisualStyleElement.ComboBox.ReadOnlyButton.Normal;
#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.

public static VisualStyleRenderer VisualStyleRenderer
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ namespace System.Windows.Forms;

public partial class DataGridViewRowHeaderCell : DataGridViewHeaderCell
{
private static readonly VisualStyleElement s_headerElement = VisualStyleElement.Header.Item.Normal;
#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.
private static readonly VisualStyleElement s_headerElement = Application.IsDarkModeEnabled
? VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ItemsViewThemeIdentifier}::Header", 1, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for the "Header".

: VisualStyleElement.Header.Item.Normal;
#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.

private static Bitmap? s_rightArrowBmp;
private static Bitmap? s_leftArrowBmp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ namespace System.Windows.Forms;

public partial class DataGridViewTopLeftHeaderCell : DataGridViewColumnHeaderCell
{
private static readonly VisualStyleElement s_headerElement = VisualStyleElement.Header.Item.Normal;
#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.
private static readonly VisualStyleElement s_headerElement = Application.IsDarkModeEnabled
? VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}_{Control.ItemsViewThemeIdentifier}::Header", 1, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here! 😺

: VisualStyleElement.Header.Item.Normal;
#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.

private const byte DATAGRIDVIEWTOPLEFTHEADERCELL_horizontalTextMarginLeft = 1;
private const byte DATAGRIDVIEWTOPLEFTHEADERCELL_horizontalTextMarginRight = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,13 @@ protected override void OnHandleCreated(EventArgs e)
0, 0, 0, 0,
SET_WINDOW_POS_FLAGS.SWP_NOMOVE | SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_NOACTIVATE);
}

#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.
if (Application.IsDarkModeEnabled)
{
PInvoke.SendMessage(tooltipHwnd, PInvoke.TTM_SETWINDOWTHEME, default, "DarkMode_Explorer");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use the existing const here?

}
#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.
}

// Add the pages
Expand Down Expand Up @@ -1288,6 +1295,17 @@ protected override void OnHandleCreated(EventArgs e)
}

UpdateTabSelection(false);
// TabControl didn't have Tab Appearance in Dark mode theme to support Dark Mode Tab Appearance we need to draw The buttons in paint event.

#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.
if (Application.IsDarkModeEnabled && GetStyle(ControlStyles.ApplyThemingImplicitly))
{
_ = PInvoke.SetWindowTheme(
hwnd: HWND,
pszSubAppName: null,
pszSubIdList: $"{DarkModeIdentifier}::{BannerContainerThemeIdentifier}");
}
#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.
}

protected override void OnHandleDestroyed(EventArgs e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System.Drawing;
using System.Windows.Forms.VisualStyles;

namespace System.Windows.Forms;

/// <summary>
Expand Down Expand Up @@ -144,7 +143,16 @@ public static void DrawTabPage(Graphics g, Rectangle bounds)

internal static void DrawTabPage(IDeviceContext deviceContext, Rectangle bounds)
{
InitializeRenderer(VisualStyleElement.Tab.Pane.Normal, 0);
#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.
// Using DarkMode Theme Subclass.
// see https://learn.microsoft.com/windows/win32/controls/theme-subclasses.
VisualStyleElement darkTabPaneElement = VisualStyleElement.CreateElement($"{Control.DarkModeIdentifier}::{Control.NavPaneThemeIdentifier}", 0, 0);
VisualStyleElement lightTabPaneElement = VisualStyleElement.Tab.Pane.Normal;
VisualStyleElement tabPaneElement = Application.IsDarkModeEnabled
? darkTabPaneElement
: lightTabPaneElement;
InitializeRenderer(tabPaneElement, 0);
#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.
t_visualStyleRenderer.DrawBackground(deviceContext, bounds);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Drawing;
using System.Drawing.Interop;
using System.Windows.Forms.Analyzers.Diagnostics;
using Microsoft.Win32;

namespace System.Windows.Forms.VisualStyles;
Expand Down Expand Up @@ -65,6 +66,37 @@ public static bool IsSupported
}
}

/// <summary>
/// <para>
/// Gets a value specifying whether the operating system has Dark Mode visual styles subclass and the Application can use this subclass to draw controls with Dark Mode theme.
///</para>
///<para>
///<return>
///<para> Returns true if Visual Style Dark Mode subclass is: </para>
/// <para> 1) Supported by the operating system.</para>
/// <para> 2) Enabled in the client area.</para>
/// <para> 3) operating system not ruining in high contrast mode</para>
/// <para> Otherwise, returns false. Note that if false is returned, attempts to create/use objects of this class will throw exceptions.</para>
///</return>
///</para>
/// </summary>
Comment on lines +69 to +82
Copy link
Member

@lonitra lonitra Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// <summary>
/// <para>
/// Gets a value specifying whether the operating system has Dark Mode visual styles subclass and the Application can use this subclass to draw controls with Dark Mode theme.
///</para>
///<para>
///<return>
///<para> Returns true if Visual Style Dark Mode subclass is: </para>
/// <para> 1) Supported by the operating system.</para>
/// <para> 2) Enabled in the client area.</para>
/// <para> 3) operating system not ruining in high contrast mode</para>
/// <para> Otherwise, returns false. Note that if false is returned, attempts to create/use objects of this class will throw exceptions.</para>
///</return>
///</para>
/// </summary>
/// <summary>
/// Gets a value specifying whether the operating system has Dark Mode visual styles subclass and the Application can use this subclass to draw controls with Dark Mode theme.
///</summary>
/// <return>
/// <see langword="true"/> if Visual Style Dark Mode subclass is supported by the operating system,
/// enabled in the client area, and operating system not running high contrast mode.
/// Otherwise, returns <see langword="false"/>. Note that if <see langword="false"/> is returned, attempts to create/use objects of this class will throw exceptions.
/// </return>

[Experimental(DiagnosticIDs.ExperimentalDarkMode, UrlFormat = DiagnosticIDs.UrlFormat)]
public static bool IsDarkModeSupported
memoarfaa marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

@lonitra lonitra Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point we cannot add new public API for net 9 RC2. Does this need to be public to fix rendering issues?

{
get
{
bool supported = AreClientAreaVisualStylesSupported;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too invasive a change this late in the game.
Can we revert this to the existing method, because that had been tested exhaustively?


if (supported)
{
HTHEME hTheme = GetHandle($"{Control.DarkModeIdentifier}_{Control.ExplorerThemeIdentifier}::BUTTON", false); // Button is an arbitrary choice.
supported = !hTheme.IsNull && !SystemInformation.HighContrast;
}

return supported;
}
}

/// <summary>
/// Returns true if the element is defined by the current visual style, else false.
/// Note:
Expand Down