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

[Dark Mode] Button with FlatStyle 'Standard' is not in dark mode on 100% dpi after enabled SystemColorMode.Dark #11949

Open
Olina-Zhang opened this issue Aug 21, 2024 · 2 comments
Labels
area-DarkMode Issues relating to Dark Mode feature help wanted Good issue for external contributors tenet-accessibility MAS violation, UIA issue; problems with accessibility standards
Milestone

Comments

@Olina-Zhang
Copy link
Member

Olina-Zhang commented Aug 21, 2024

.NET version

9.0.0-rc.1.24418.2 + private dlls built from winforms repo main branch

Did it work in .NET Framework?

No

Did it work in any of the earlier releases of .NET Core or .NET 5+?

This is a new feature Dark Mode: #11857

Issue description

On 100% DPI, Button with FlatStyle 'Standard' is not in dark mode after enabled SystemColorMode.Dark, it cannot repro when monitor's dpi is greater than 100%.

on 100%DPI:
image

on 150%DPI:
image

Steps to reproduce

  1. Create a WinForms .NET application with button control, set button's FlatStyle == Standard
  2. Enable DarkMode by Application.SetColorMode(SystemColorMode.Dark) in Program.cs file
  3. Run the application to observe
@Olina-Zhang Olina-Zhang added untriaged The team needs to look at this issue in the next triage area-DarkMode Issues relating to Dark Mode feature tenet-accessibility MAS violation, UIA issue; problems with accessibility standards labels Aug 21, 2024
@merriemcgaw merriemcgaw added help wanted Good issue for external contributors and removed untriaged The team needs to look at this issue in the next triage labels Sep 4, 2024
Copy link
Contributor

This issue is now marked as "help wanted", and we’re looking for a community volunteer to work on this issue. If we receive no interest in 180 days, we will close the issue. To learn more about how we handle feature requests, please see our documentation.

Happy Coding!

@gerhardol
Copy link

A fix for this (and similar) issues is to set the back color when loading the form

In the (base) form constructor

Load += (s, e) => ((Form)s!).FixVisualStyle();
public static class ThemeFix
{
    private static readonly ConditionalWeakTable<IWin32Window, IWin32Window> AlreadyFixedControls =
        [];

    private static readonly ConditionalWeakTable<IWin32Window, IWin32Window> AlreadyFixedContextMenuOwners =
        [];

    public static ThemeSettings ThemeSettings { private get; set; } = ThemeSettings.Default;

    public static void FixVisualStyle(this Control container)
    {
        container.DescendantsToFix<Button>()
            .ForEach(SetupButton);
    }

    private static IEnumerable<TControl> DescendantsToFix<TControl>(this Control c)
        where TControl : Control
    {
        return c.FindDescendantsOfType<TControl>(SkipThemeAware)
            .Where(control => TryAddToWeakTable(control, AlreadyFixedControls));
    }

    private static bool SkipThemeAware(Control c) =>
        c.GetType().GetCustomAttribute<ThemeAwareAttribute>() is not null;
        private static void SetupButton(this Button button)
        {
            // .net9 fix for https://github.com/dotnet/winforms/issues/11949 (only supposed to occur for 100%)
#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 && button.FlatStyle == FlatStyle.Standard)
            {
                button.TouchBackColor();
            }
#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 void TouchBackColor(this Control c)
        {
            c.BackColor = c.BackColor;
        }

        private static void TouchForeColor(this Control c)
        {
            c.ForeColor = c.ForeColor;
        }

        private static bool TryAddToWeakTable(IWin32Window element, ConditionalWeakTable<IWin32Window, IWin32Window> weakTable)
        {
            if (weakTable.TryGetValue(element, out _))
            {
                return false;
            }

            weakTable.Add(element, element);
            return true;
        }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-DarkMode Issues relating to Dark Mode feature help wanted Good issue for external contributors tenet-accessibility MAS violation, UIA issue; problems with accessibility standards
Projects
None yet
Development

No branches or pull requests

3 participants