How can i get the default accent color in Windows 10?

Viewed 1805

I have an application and i want to make its background color as default Windows 10 Accent color and when user changes Windows 10's Accent color i want my application's background color also changes.

enter image description here

3 Answers

You would need to make a call to UISettings.GetColorValue(UIColorType.Background) as documented here.

WinForms is an old technology that has not been updated much to support new OS features. There is no good way to get the Accent color using the base .Net libraries (though there is an registry based hack using undocumented keys to retrieve the value). Fortunately, you can access some of the Windows Runtime APIs by adding the NUGET package Microsoft.Windows.SDK.Contracts.

With this package added, you can create an instance of the Windows.UI.ViewManagement.UISettings Class and then use the UISettings.GetColorValue(UIColorType) Method to retrieve the value.

To be notified of changes to the value, you can subscribe to the SystemEvents.UserPreferenceChanged Event. This event categorizes the change as a UserPreferenceCategory.General type change that is the default when the old logic does not know what has changed (again old code not updated for new features). You could detect changes by listenimg for the WM_SETTINGCHANGE message and check for when the WParam is null and the LParam points to a string ("ImmersiveColorSet"), but this replies upon the string value never changing and is not much better than reacting to all UserPreferenceCategory.General changes.

With all that stated, a simple implementation would be as follows:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        UserPreferenceChangedEventHandler UserPerferenceChanged = (s, e) =>
        { if (e.Category == UserPreferenceCategory.General || e.Category == UserPreferenceCategory.VisualStyle) BackColor = GetAccentColor(); };

        SystemEvents.UserPreferenceChanged += UserPerferenceChanged;
        Disposed += (object s, EventArgs e) => { SystemEvents.UserPreferenceChanged -= UserPerferenceChanged; };
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        BackColor = GetAccentColor();
    }

    static Windows.UI.ViewManagement.UISettings uiSettings = new Windows.UI.ViewManagement.UISettings();
    private static System.Drawing.Color GetAccentColor()
    {
        Windows.UI.Color c = uiSettings.GetColorValue(Windows.UI.ViewManagement.UIColorType.Accent);
        return Color.FromArgb(c.A, c.R, c.G, c.B);
    }
}

You can override WndProc to handle the WM_SETTINGCHANGE message.
When this message is received, you can determine whether the settings change is related to a Desktop change inspecting the Message WParam: if it's SPI_SETDESKWALLPAPER, then Desktop settings have changed.

A change in the Background Color is notified like this.
When you get the message, the Color value has already been changed so you can retrive it using the SystemColors class: SystemColors.Desktop returns the current Color of the Desktop.

private const int WM_SETTINGCHANGE = 0x001A;
private const int SPI_SETDESKWALLPAPER = 0x0014;

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);
    switch (m.Msg) {
        case WM_SETTINGCHANGE:
            if (m.WParam.ToInt32() == SPI_SETDESKWALLPAPER) {
                this.BackColor = SystemColors.Desktop;
            }
            m.Result = IntPtr.Zero;
            break;
        // other case switches
} 
Related