System.Drawing.SystemColor
值缓存在KnownColorsTable
类中的私有数组colorTable
中。随着使用 Win32 API 请求的系统颜色更改,数组的内容会被填充和更新。
要更改应用程序范围内的系统颜色,请colorTable
根据您想要的值更改存储的颜色值。
然后你还需要为SystemBrushes
和SystemPens
类清空缓存,因为钢笔和画笔不会自己重新读取 RBG 值。
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; }
}
}
一个更完整的例子,说明我如何为我的爱好项目做到这一点。
应在加载应用程序之前更改系统颜色,以确保控件在初始化时看到更改的值。您将需要使用 Win32 API 直接呈现自身的控件的其他技巧,例如ListView
或TreeView
.
您可以在此处阅读详细信息。这是俄语的机器翻译。