Skip to content

Commit

Permalink
Fix issues with SystemColors and UseAlternativeColorSet.
Browse files Browse the repository at this point in the history
  • Loading branch information
KlausLoeffelmann committed Aug 1, 2024
1 parent a83fbb4 commit c20c31c
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 8 deletions.
20 changes: 19 additions & 1 deletion src/System.Drawing.Common/src/System/Drawing/SystemBrushes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ namespace System.Drawing;

public static class SystemBrushes
{
#if NET9_0_OR_GREATER
#pragma warning disable SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
private static bool s_colorSetOnLastAccess = SystemColors.UseAlternativeColorSet;
#pragma warning restore SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#endif
private static readonly object s_systemBrushesKey = new();

public static Brush ActiveBorder => FromSystemColor(SystemColors.ActiveBorder);
Expand Down Expand Up @@ -57,7 +62,20 @@ public static Brush FromSystemColor(Color c)
throw new ArgumentException(SR.Format(SR.ColorNotSystemColor, c.ToString()));
}

if (!Gdip.ThreadData.TryGetValue(s_systemBrushesKey, out object? tempSystemBrushes) || tempSystemBrushes is not Brush[] systemBrushes)
#if NET9_0_OR_GREATER
#pragma warning disable SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
if (s_colorSetOnLastAccess != SystemColors.UseAlternativeColorSet)
{
s_colorSetOnLastAccess = SystemColors.UseAlternativeColorSet;

// We need to clear the SystemBrushes cache, when the ColorMode had changed.
Gdip.ThreadData.Remove(s_systemBrushesKey);
}
#pragma warning restore SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#endif

if (!Gdip.ThreadData.TryGetValue(s_systemBrushesKey, out object? tempSystemBrushes)
|| tempSystemBrushes is not Brush[] systemBrushes)
{
systemBrushes = new Brush[(int)KnownColor.WindowText + (int)KnownColor.MenuHighlight - (int)KnownColor.YellowGreen];
Gdip.ThreadData[s_systemBrushesKey] = systemBrushes;
Expand Down
21 changes: 20 additions & 1 deletion src/System.Drawing.Common/src/System/Drawing/SystemPens.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ namespace System.Drawing;

public static class SystemPens
{
#if NET9_0_OR_GREATER
#pragma warning disable SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
private static bool s_colorSetOnLastAccess = SystemColors.UseAlternativeColorSet;
#pragma warning restore SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#endif

private static readonly object s_systemPensKey = new();

public static Pen ActiveBorder => FromSystemColor(SystemColors.ActiveBorder);
Expand Down Expand Up @@ -58,7 +64,20 @@ public static Pen FromSystemColor(Color c)
throw new ArgumentException(SR.Format(SR.ColorNotSystemColor, c.ToString()));
}

if (!Gdip.ThreadData.TryGetValue(s_systemPensKey, out object? tempSystemPens) || tempSystemPens is not Pen[] systemPens)
#if NET9_0_OR_GREATER
#pragma warning disable SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
if (s_colorSetOnLastAccess != SystemColors.UseAlternativeColorSet)
{
s_colorSetOnLastAccess = SystemColors.UseAlternativeColorSet;

// We need to clear the SystemBrushes cache, when the ColorMode had changed.
Gdip.ThreadData.Remove(s_systemPensKey);
}
#pragma warning restore SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#endif

if (!Gdip.ThreadData.TryGetValue(s_systemPensKey, out object? tempSystemPens)
|| tempSystemPens is not Pen[] systemPens)
{
systemPens = new Pen[(int)KnownColor.WindowText + (int)KnownColor.MenuHighlight - (int)KnownColor.YellowGreen];
Gdip.ThreadData[s_systemPensKey] = systemPens;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ internal static unsafe void DrawLines(this HDC hdc, HPEN hpen, ReadOnlySpan<int>
}
}

internal static Color FindNearestColor(this DeviceContextHdcScope hdc, Color color) => FindNearestColor(hdc.HDC, color);
internal static Color FindNearestColor(this DeviceContextHdcScope hdc, Color color) =>
FindNearestColor(hdc.HDC, color);

/// <summary>
/// Calls <see cref="PInvoke.GetNearestColor(HDC, COLORREF)"/> to get the nearest color for the given
Expand All @@ -116,7 +117,22 @@ internal static unsafe void DrawLines(this HDC hdc, HPEN hpen, ReadOnlySpan<int>
/// </remarks>
internal static Color FindNearestColor(this HDC hdc, Color color)
{
Color newColor = ColorTranslator.FromWin32((int)PInvoke.GetNearestColor(hdc, (COLORREF)(uint)ColorTranslator.ToWin32(color)).Value);
#pragma warning disable SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
if (color.IsSystemColor && SystemColors.UseAlternativeColorSet)
{
// We need to "un-system" the color for nearest color to work correctly in dark mode,
// since GetNearestColor doesn't understand dark mode system colors and internally works
// with the light mode colors.
color = Color.FromArgb(color.ToArgb());
Debug.Assert(!color.IsSystemColor, "Color should not be a system color.");
}
#pragma warning restore SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

Color newColor = ColorTranslator.FromWin32(
(int)PInvoke.GetNearestColor(
hdc: hdc,
color: (COLORREF)(uint)ColorTranslator.ToWin32(color)).Value);

return newColor.ToArgb() == color.ToArgb() ? color : newColor;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ internal readonly ref struct CreateBrushScope
/// </summary>
public CreateBrushScope(Color color)
{
HBRUSH = color.IsSystemColor
#pragma warning disable SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
HBRUSH = color.IsSystemColor && !SystemColors.UseAlternativeColorSet
? PInvoke.GetSysColorBrush(color)
: PInvoke.CreateSolidBrush(color);
#pragma warning restore SYSLIB5002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

ValidateBrushHandle();
}

Expand Down
4 changes: 3 additions & 1 deletion src/System.Windows.Forms/src/System/Windows/Forms/Control.cs
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,8 @@ internal HBRUSH BackColorBrush
Color color = BackColor;
HBRUSH backBrush;

if (color.IsSystemColor)
#pragma warning disable WFO9001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
if (color.IsSystemColor && !Application.IsDarkModeEnabled)
{
backBrush = PInvoke.GetSysColorBrush(color);
SetState(States.OwnCtlBrush, false);
Expand All @@ -728,6 +729,7 @@ internal HBRUSH BackColorBrush
backBrush = PInvoke.CreateSolidBrush((COLORREF)(uint)ColorTranslator.ToWin32(color));
SetState(States.OwnCtlBrush, true);
}
#pragma warning restore WFO9001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

Debug.Assert(!backBrush.IsNull, "Failed to create brushHandle");
Properties.SetObject(s_backBrushProperty, backBrush);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,6 @@ protected override void OnDrawItem(DrawItemEventArgs e)
textBounds.X = bounds.X;
}

#pragma warning disable WFO9001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
Color backColor = (SelectionMode != SelectionMode.None) ? e.BackColor : BackColor;
Color foreColor = (SelectionMode != SelectionMode.None) ? e.ForeColor : ForeColor;
if (!Enabled)
Expand All @@ -605,7 +604,6 @@ protected override void OnDrawItem(DrawItemEventArgs e)
foreColor = SystemColors.GrayText;
}
}
#pragma warning restore WFO9001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

// Draw the text

Expand Down

0 comments on commit c20c31c

Please sign in to comment.