Correct System.Windows.Forms.ControlPaint.HSLColor.Darker function
Opened this issue · 0 comments
Background and motivation
At least since .NET Framework 4, the System.WIndows.Forms.ControlPaint.HSLColor.Darker
function (which is called by System.Windows.Forms.ControlPaint.Dark()
) has been wrong for non-system colors.
The Lighter
function logically interpolates, based on the passed percentage value, from the current luminosity towards a luminosity value 50% higher. The Darker
function illogically interpolates, based on the passed percentage value, from a luminosity value 33% lower than the current luminosity towards zero.
A call to Lighter(0)
reasonably returns the same color. A call to Darker(0)
unreasonably returns a color 33% darker. Lighter(0.5)
returns a color 25% lighter; Darker(0.5)
returns a color 67% darker. Lighter(1)
returns a color 50% lighter; Darker(1)
returns black.
API Proposal
namespace System.Windows.Forms;
public static partial class ControlPaint
{
private readonly struct HLSColor : IEquatable<HLSColor>
{
public Color Darker(float percDarker)
{
if (!_isSystemColors_Control)
{
// *** this block is the only changed code ***
// match the Lighter function and use current luminosity as a baseline instead of zero
int zeroLum = luminosity;
int oneLum = NewLuma(ShadowAdjustment, true);
return ColorFromHLS(_hue, zeroLum + (int)((oneLum - zeroLum) * percDarker), _saturation);
}
else
{
// With the usual color scheme, ControlDark/DarkDark is not exactly
// what we would otherwise calculate
if (percDarker == 0.0f)
{
return SystemColors.ControlDark;
}
else if (percDarker == 1.0f)
{
return SystemColors.ControlDarkDark;
}
else
{
ARGB dark = SystemColors.ControlDark;
ARGB darkDark = SystemColors.ControlDarkDark;
return Color.FromArgb(
(byte)(dark.R - (byte)((dark.R - darkDark.R) * percDarker)),
(byte)(dark.G - (byte)((dark.G - darkDark.G) * percDarker)),
(byte)(dark.B - (byte)((dark.B - darkDark.B) * percDarker)));
}
}
}
}
}
API Usage
using System.Drawing.Color;
Color c = Color.FromArgb(128, 128, 128);
Color sameColor = System.Windows.Forms.ControlPaint.Dark(c, 0.0);
Color darkColor = System.Windows.Forms.ControlPaint.Dark(c, 0.5);
Color darkerColor = System.Windows.Forms.ControlPaint.Dark(c, 1.0);
Color approxSameColor = System.Windows.Forms.ControlPaint.Light(System.Windows.Forms.ControlPaint.Dark(c));
Color approxSameColor2 = System.Windows.Forms.ControlPaint.Dark(System.Windows.Forms.ControlPaint.Light(c));
Alternative Designs
No response
Risks
No response
Will this feature affect UI controls?
Yes.
- no
- none
- no