简体   繁体   中英

Is there a way to respond to a change of System colors at design time?

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

You can subscribe to the SystemEvents.DisplaySettingsChanged event, I believe.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM