Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@AEAEAEAE4343
Last active May 10, 2021 22:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AEAEAEAE4343/aa97b220a42eb48201004ea849c2da00 to your computer and use it in GitHub Desktop.
Save AEAEAEAE4343/aa97b220a42eb48201004ea849c2da00 to your computer and use it in GitHub Desktop.
Windows color schemes registry reverse-engineered into a C# class
public class ColorScheme
{
[StructLayout(LayoutKind.Explicit, Size = 712, Pack = 1)]
private struct ColorSchemeStruct
{
[FieldOffset(8)]
public byte WindowBorderSize;
[FieldOffset(12)]
public byte ScrollBarSize1;
[FieldOffset(16)]
public byte ScrollBarSize2;
[FieldOffset(20)]
public byte CaptionSize1;
[FieldOffset(24)]
public byte CaptionSize2;
[FieldOffset(56), MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] CaptionFont;
[FieldOffset(120)]
public byte PaletteTitleSize;
[FieldOffset(156), MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] PaletteTitleFont;
[FieldOffset(220)]
public byte MenuSize;
[FieldOffset(256), MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] MenuFont;
[FieldOffset(348), MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] ToolTipFont;
[FieldOffset(440), MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] MessageBoxFont;
[FieldOffset(532), MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] IconFont;
[FieldOffset(600), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] DesktopColor;
[FieldOffset(604), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] ActiveTitleBarColor;
[FieldOffset(608), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] InactiveTitleBarColor;
[FieldOffset(612), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] MenuColor;
[FieldOffset(616), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] WindowColor;
[FieldOffset(624), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] MenuFontColor;
[FieldOffset(628), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] MessageBoxFontColor;
[FieldOffset(632), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] ActiveTitleBarFontColor;
[FieldOffset(636), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] ActiveWindowBorderColor;
[FieldOffset(640), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] InactiveWindowBorderColor;
[FieldOffset(644), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] ApplicationBackgroundColor;
[FieldOffset(648), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] SelectedItemsColor;
[FieldOffset(672), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] InactiveTitleBarFontColor;
[FieldOffset(688), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] ToolTipFontColor;
[FieldOffset(692), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] ToolTipColor;
[FieldOffset(704), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] ActiveTitleBarGradientColor;
[FieldOffset(708), MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] InactiveTitleBarGradientColor;
}
public byte WindowBorderSize { get => str.WindowBorderSize; set => str.WindowBorderSize = value; }
public byte ScrollBarSize { get => str.ScrollBarSize1; set { str.ScrollBarSize1 = value; str.ScrollBarSize2 = value; } }
public byte CaptionSize { get => str.CaptionSize1; set { str.CaptionSize1 = value; str.CaptionSize2 = value; } }
public string CaptionFont { get => GetStringFromBytes(str.CaptionFont); set => str.CaptionFont = GetBytesFromString(value); }
public byte PaletteTitleSize { get => str.PaletteTitleSize; set => str.PaletteTitleSize = value; }
public string PaletteTitleFont { get => GetStringFromBytes(str.PaletteTitleFont); set => str.PaletteTitleFont = GetBytesFromString(value); }
public byte MenuSize { get => str.MenuSize; set => str.MenuSize = value; }
public string MenuFont { get => GetStringFromBytes(str.MenuFont); set => str.MenuFont = GetBytesFromString(value); }
public string ToolTipFont { get => GetStringFromBytes(str.ToolTipFont); set => str.ToolTipFont = GetBytesFromString(value); }
public string MessageBoxFont { get => GetStringFromBytes(str.MessageBoxFont); set => str.MessageBoxFont = GetBytesFromString(value); }
public string IconFont { get => GetStringFromBytes(str.IconFont); set => str.IconFont = GetBytesFromString(value); }
public Color DesktopColor { get => GetColorFromBytes(str.DesktopColor); set => str.DesktopColor = GetBytesFromColor(value); }
public Color ActiveTitleBarColor { get => GetColorFromBytes(str.ActiveTitleBarColor); set => str.ActiveTitleBarColor = GetBytesFromColor(value); }
public Color InactiveTitleBarColor { get => GetColorFromBytes(str.InactiveTitleBarColor); set => str.InactiveTitleBarColor = GetBytesFromColor(value); }
public Color MenuColor { get => GetColorFromBytes(str.MenuColor); set => str.MenuColor = GetBytesFromColor(value); }
public Color WindowColor { get => GetColorFromBytes(str.WindowColor); set => str.WindowColor = GetBytesFromColor(value); }
public Color MenuFontColor { get => GetColorFromBytes(str.MenuFontColor); set => str.MenuFontColor = GetBytesFromColor(value); }
public Color MessageBoxFontColor { get => GetColorFromBytes(str.MessageBoxFontColor); set => str.MessageBoxFontColor = GetBytesFromColor(value); }
public Color ActiveTitleBarFontColor { get => GetColorFromBytes(str.ActiveTitleBarFontColor); set => str.ActiveTitleBarFontColor = GetBytesFromColor(value); }
public Color ActiveWindowBorderColor { get => GetColorFromBytes(str.ActiveWindowBorderColor); set => str.ActiveWindowBorderColor = GetBytesFromColor(value); }
public Color InactiveWindowBorderColor { get => GetColorFromBytes(str.InactiveWindowBorderColor); set => str.InactiveWindowBorderColor = GetBytesFromColor(value); }
public Color ApplicationBackgroundColor { get => GetColorFromBytes(str.ApplicationBackgroundColor); set => str.ApplicationBackgroundColor = GetBytesFromColor(value); }
public Color SelectedItemsColor { get => GetColorFromBytes(str.SelectedItemsColor); set => str.SelectedItemsColor = GetBytesFromColor(value); }
public Color InactiveTitleBarFontColor { get => GetColorFromBytes(str.InactiveTitleBarFontColor); set => str.InactiveTitleBarFontColor = GetBytesFromColor(value); }
public Color ToolTipFontColor { get => GetColorFromBytes(str.ToolTipFontColor); set => str.ToolTipFontColor = GetBytesFromColor(value); }
public Color ToolTipColor { get => GetColorFromBytes(str.ToolTipColor); set => str.ToolTipColor = GetBytesFromColor(value); }
public Color ActiveTitleBarGradientColor { get => GetColorFromBytes(str.ActiveTitleBarGradientColor); set => str.ActiveTitleBarGradientColor = GetBytesFromColor(value); }
public Color InactiveTitleBarGradientColor { get => GetColorFromBytes(str.InactiveTitleBarGradientColor); set => str.InactiveTitleBarGradientColor = GetBytesFromColor(value); }
ColorSchemeStruct str;
public ColorScheme()
{
str = new ColorSchemeStruct();
}
private ColorScheme(ColorSchemeStruct structure)
{
str = structure;
}
public static ColorScheme FromColorScheme(byte[] colorScheme)
{
if (colorScheme.Length != 712)
throw new ArgumentException("Not enough data to fill struct.");
IntPtr buffer = Marshal.AllocHGlobal(712);
Marshal.Copy(colorScheme, 0, buffer, 712);
ColorSchemeStruct retobj = (ColorSchemeStruct)Marshal.PtrToStructure(buffer, typeof(ColorSchemeStruct));
Marshal.FreeHGlobal(buffer);
return new ColorScheme(retobj);
}
public byte[] ToColorScheme()
{
IntPtr buffer = Marshal.AllocHGlobal(712);
Marshal.StructureToPtr(str, buffer, false);
byte[] colorScheme = new byte[712];
Marshal.Copy(buffer, colorScheme, 0, 712);
Marshal.FreeHGlobal(buffer);
return colorScheme;
}
private Color GetColorFromBytes(byte[] bytes) => Color.FromArgb(bytes[0], bytes[1], bytes[2]);
private byte[] GetBytesFromColor(Color color) => new byte[] { color.R, color.G, color.B };
private string GetStringFromBytes(byte[] bytes)
{
if (bytes.Length != 64)
throw new ArgumentException("The array was not 64 bytes long");
byte[] newBytes = new byte[32];
for (int i = 0; i < 32; i++)
newBytes[i] = bytes[i * 2];
return Encoding.ASCII.GetString(newBytes).Trim('\0');
}
private byte[] GetBytesFromString(string text)
{
if (text.Length > 32)
throw new ArgumentException("The string was longer than 32 characters");
byte[] bytes = Encoding.ASCII.GetBytes(text);
byte[] newBytes = new byte[64];
for (int i = 0; i < 64; i++)
newBytes[i] = 0;
for (int i = 0; i < bytes.Length; i++)
newBytes[i * 2] = bytes[i];
return newBytes;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment