System.Drawing.SystemColor
values are cached within KnownColorsTable
class in a private array colorTable
. The content of the array is populated and updated as system colors change using Win32 API requests.
To change the system colors in scope of your application, change color values stored in colorTable
by the values you want.
Then you also need to clear the cache for SystemBrushes
and SystemPens
class, because the pens and brushes will not re-read RBG values by themselves.
using System.Drawing;
using System.Reflection;
namespace Example
{
public class SystemColorsUtility
{
public SystemColorsUtility()
{
// force init color table
byte unused = SystemColors.Window.R;
var colorTableField = typeof(Color).Assembly.GetType("System.Drawing.KnownColorTable")
.GetField("colorTable", BindingFlags.Static | BindingFlags.NonPublic);
_colorTable = (int[]) colorTableField.GetValue(null);
_threadDataProperty = systemDrawingAssembly.GetType("System.Drawing.SafeNativeMethods")
.GetNestedType("Gdip", BindingFlags.NonPublic)
.GetProperty("ThreadData", BindingFlags.Static | BindingFlags.NonPublic);
SystemBrushesKey = typeof(SystemBrushes)
.GetField("SystemBrushesKey", BindingFlags.Static | BindingFlags.NonPublic)
.GetValue(null);
SystemPensKey = typeof(SystemPens)
.GetField("SystemPensKey", BindingFlags.Static | BindingFlags.NonPublic)
.GetValue(null);
}
public void SetColor(KnownColor knownColor, Color value)
{
_colorTable[(int) knownColor] = value.ToArgb();
ThreadData[SystemBrushesKey] = null;
ThreadData[SystemPensKey] = null;
}
private int[] _colorTable;
private object SystemBrushesKey { get; }
private object SystemPensKey { get; }
}
}
A more complete example of how I did it for my hobby project.
System colors should be changed before the application is loaded to ensure the controls see changed values on initialization. You will need additional tricks with controls using Win32 API directly to render themselves, such as ListView
or TreeView
.
You can read details on that here. It's a machine translation from Russian.
control.BackColor = control.BackColor
3. Some controls need to haveFlatStyle.Flat
to completely rely onBackColor / ForeColor
properties – Litigation