有没有办法在设计时响应系统颜色的变化?

发布于 2024-11-05 04:27:54 字数 2233 浏览 6 评论 0原文

我有一个用户控件(源自 ContainerControl),我使用渐变填充它。第一个渐变颜色可能是也可能不是系统颜色,例如 SystemColors.Highlight。 第二个渐变颜色是通过 ControlPaint.Light(firstColor) 或类似方法从第一个渐变颜色派生出来的。

我可以通过重写 OnSystemColorsChanged 轻松处理运行时系统颜色的变化,并且它的工作没有任何问题。但是,如果在设计时将控件放置在窗体上,然后更改系统颜色,则第二个颜色保持不变,这可能是由于在设计时未调用 OnSystemColorsChanged 所致。

我可以手动重置第二个颜色,因为我为第二个颜色属性提供 ShouldSerialize- 和 Reset- 方法,因此当系统颜色更改时,该属性的默认值也会相应更改。

那么,有什么方法可以在设计时捕获系统颜色的变化吗?

编辑:

这是一个最小化的代码示例:

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();
}
}

如果将此控件放到窗体上,此代码将执行以下操作:

  • 默认 Color1 为 SystemColors.Highlight

  • 默认 Color2 为较浅的颜色

  • 如果 Color2 没有手动更改,它将自动从 Color1 派生

  • 如果系统颜色在运行时改变,Color1和Color2都会改变

  • 如果系统颜色在设计时改变,只有Color1会改变< /p>

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萌逼全场 2024-11-12 04:27:54

如果事件在设计模式下被抑制,我不会感到太惊讶,SystemEvents 很棘手,因为它们是静态事件。通过在 Color2 的属性设置器中设置 bool 标志以指示它与默认颜色匹配来解决您的问题。设置标志时始终使用 ControlPaint.Light()。

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.

说谎友 2024-11-12 04:27:54

您可以订阅 SystemEvents.DisplaySettingsChanged 事件,我相信。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文