I've got a usercontrol (derived from ContainerControl) which I'm filling using a gradient. The first gradient color may or may not be a system color, like SystemColors.Highlight
.
The second gradient color is derived from the first one, by means of ControlPaint.Light(firstColor)
or something similar.
I can easily handle changing system colors at runtime by overriding OnSystemColorsChanged
, and it works without any trouble. But if the control is placed on a form at design time, and then the system colors are changed, the second color stays the same, probably due to OnSystemColorsChanged
not being called at design time.
I can reset the second color manually since I provide ShouldSerialize- and Reset- methods for the second color property, and therefore the default value for that property changes accordingly when the system color changes.
So, is there any way to catch a system color change at design time?
Edit:
Here's a minimized code sample:
public class Test : ContainerControl
{
public Test()
{
ResetColor1();
ResetColor2();
}
private bool _resetColor2;
// Color 1 stuff
private Color _color1 = Color.Empty;
public System.Drawing.Color Color1
{
get { return _color1; }
set
{
_resetColor2 = !ShouldSerializeColor2();
_color1 = value;
if (_resetColor2)
ResetColor2();
Invalidate();
}
}
// Defaults Color 1
private Color DefaultColor1 { get { return SystemColors.Highlight; } }
public bool ShouldSerializeColor1()
{
return !Color1.Equals(Color.Empty) && !Color1.Equals(DefaultColor1);
}
public void ResetColor1()
{
Color1 = DefaultColor1;
}
// Color 2 stuff
private Color _color2 = Color.Empty;
public System.Drawing.Color Color2
{
get { return _color2; }
set
{
_color2 = value;
Invalidate();
}
}
private Color DefaultColor2 { get { return ControlPaint.Light(Color1); } }
public bool ShouldSerializeColor2()
{
return !Color2.Equals(DefaultColor2);
}
public void ResetColor2()
{
Color2 = DefaultColor2;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (LinearGradientBrush b = new LinearGradientBrush(ClientRectangle, Color1, Color2, LinearGradientMode.ForwardDiagonal))
e.Graphics.FillRectangle(b, this.ClientRectangle);
}
protected override void OnSystemColorsChanged(EventArgs e)
{
base.OnSystemColorsChanged(e);
if (_resetColor2)
ResetColor2();
}
}
If you put this control onto a form, this code will do the following:
Default Color1 to SystemColors.Highlight
Default Color2 to a lighter color
If Color2 is not changed manually, it will automatically derive from Color1
If system colors change at runtime, Color1 and Color2 will both change
If system colors change at design time, only Color1 will change
I wouldn't be too surprised if the event is suppressed in design mode, SystemEvents are tricky because they are static events. Solve your problem by setting a bool flag in the property setter for Color2 to indicate that it matches the default color. Always use ControlPaint.Light() when the flag is set.