本文介绍了Winforms ToolStrip.BackColor 返回错误的颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 winforms 在 C# 中创建了一个非常简单的虚拟应用程序.它只包含一个 ToolStrip 和一个位于该 ToolStrip 内的 TrackBar.TrackBar 应该与 ToolStrip 具有相同的 BackColor,但似乎 ToolStrip.BackColor 属性没有返回实际的背景颜色.

I created a very simple dummy application in C# using winforms. It contains only a ToolStrip and a TrackBar inside that ToolStrip. The TrackBar should have the same BackColor as the ToolStrip, but it seems, that the property ToolStrip.BackColor does not return the actual background color.

public Form1()
{
    //// Here the ToolStrip is created.
    //// This code is generated by the designer.
    this.InitializeComponent();
    //// Here the the TrackBar is created.
    //// I think this is impossible to do via the Designer.
    this.CreateSpeedSlider();
}

private void CreateSpeedSlider()
{
    this.toolStrip.SuspendLayout();
    this.speedSlider = new TrackBar
    {
        TickStyle = TickStyle.None,
        AutoSize = false,
        Height = this.toolStrip.Height,
        Minimum = 0,
        Maximum = 10,
        BackColor = this.toolStrip.BackColor,
    };

    this.toolStrip.Items.Add(new ToolStripControlHost(this.speedSlider));
    this.toolStrip.ResumeLayout();
}

结果是浅灰色 ToolStrip 上的白色 TrackBar.所以看起来

The result is a white TrackBar on a light grey ToolStrip. So it seems that

this.toolStrip.BackColor

不返回实际用于绘制它的 ToolStrip 的背景颜色.

does not return the back color of the ToolStrip that is actually used to draw it.

如果我将函数更改为

private void CreateSpeedSlider()
{
    this.toolStrip.BackColor = this.toolStrip.BackColor;
    ...
}

我在白色 ToolStrip 上看到一个白色滑块.所以……把属性的值赋值给自己,实际上是把颜色从浅灰色变成了白色???

I get a white slider on a white ToolStrip. So ... assigning the value of the property to itself actually changes the color from light grey to white???

有没有什么好方法可以在没有此类黑客"的情况下检索 ToolStrip 的正确背景颜色?

Is there any good way to retrieve the correct background color of a ToolStrip without such 'hacks'?

这种行为是故意的还是我遗漏了什么?

And is this behaviour intentional or am I missing something?

推荐答案

BackColor 是一个环境属性

Control.BackColor 是一个环境属性:

BackColor is an ambient property

Control.BackColor is an ambient property:

BackColor 属性是一个环境属性.环境属性是一个控件属性,如果未设置,则从父控件中检索.例如,默认情况下,Button 将具有与其父 Form 相同的 BackColor.有关环境属性的更多信息,请参阅 AmbientProperties 类或 Control 类概述.

意思是这样实现的(来源):

It means that it is implemented like this (source):

public virtual Color BackColor
{
     get
     {
          Color c = RawBackColor; // inheritedProperties.BackColor
          if (!c.IsEmpty)
          {
               return c;
          }
          Control p = ParentInternal;
          if (p != null && p.CanAccessProperties)
          {
               c = p.BackColor;
               if (IsValidBackColor(c))
               {
                    return c;
               }
          }
          ...

有一个内部属性 RawBackColor,它是为这个特定控件显式设置的颜色.BackColor 本身是计算出来的 - 如果没有为这个控件显式设置颜色,它将尝试返回其父级的 BackColor.

There's an internal property RawBackColor which is the color explicitly set for this particular control. BackColor itself is calculated - if the color was not explicitly set for this control it will try to return the BackColor of its parent.

为菜单实现不同的样式ToolStrip 支持可配置的渲染:

To implement different styling for menus ToolStrip supports configurable rendering:

ToolStrip 类实现的呈现方案与其他 Windows 窗体控件明显不同.使用此方案,您可以轻松应用样式和主题.

这意味着 ToolStrip 有一个 Renderer 并且该渲染器的初始化取决于系统设置.因此,通常没有简单的方法可以获取工具条的背景颜色.

What it means, is that ToolStrip has a Renderer and that renderer's initialization depends on system settings. So, in general there's no easy way to get the back color of a toolstrip.

默认情况下,可能性很好ToolstripProfessionalRenderer.这种类型的渲染器实际上用渐变绘制背景.它有一个 ColorTable 属性,反过来定义 MenuStripGradientBeginMenuStripGradientEnd.

Odds are good that by default ToolstripProfessionalRenderer is used. This type of renderer actually paints the background with a gradient. It has a ColorTable property which, in its turn, defines MenuStripGradientBegin and MenuStripGradientEnd.

因此,在大多数(但不是全部)情况下,您可以通过以下方式确定工具提示的默认背景颜色:

So, in most (but not all) cases, you can determine the default back color for a toolstip this way:

var renderer = (ToolStripProfessionalRenderer)toolStrip.Renderer;
Console.WriteLine(renderer.ColorTable.MenuStripGradientBegin);
Console.WriteLine(renderer.ColorTable.MenuStripGradientEnd);

如果您尝试托管具有均匀绘制背景的控件,例如 TrackBar,它可能会突出显示在渐变填充的工具条中.

If you try to host a control with a uniformly-painted background, such as TrackBar, it will probably stick out in a gradient-filled toolstrip.

我在任何地方都找不到这种行为的记录,但根据 ToolStripRenderer, 如果工具条的 RawBackColor 未设置,则仅绘制背景(填充渐变):

I couldn't find this behaviour documented anywhere, but according to ToolStripRenderer source, background is only painted (filled with gradient) if tool strip's RawBackColor is not set:

internal bool ShouldPaintBackground(Control control)
{
    return (control.RawBackColor == Color.Empty && control.BackgroundImage == null);
}

因此,如果您将 ToolStrip.BackColor 显式设置为任何颜色,那么渲染器将仅使用该颜色作为背景色.这种令人困惑的行为解释了原因:

So, if you explicitly set ToolStrip.BackColor to any color, then the renderer will just use this color as a back color. This confusing behaviour explains why:

toolStrip.BackColor = toolStrip.BackColor;

有实际效果.

我可以看到很多前进的方向,但没有一个是好的:

I can see multiple ways forward, none of them good:

  1. 将工具条和轨迹栏的 BackColor 设置为某种已知颜色.这将杀死工具条背景中漂亮的渐变.如果您不太关心渐变,那是最简单的方法.

  1. Set the BackColor for both tool strip and track bar to some known color. This will kill the beautiful, beautiful gradient in toolstrip background. If you don't care much about gradient that's the easiest way to go.

使托管控件透明,以便工具条的背景显示出来.这对 TrackBar 不起作用,因为它不支持透明背景,出于某种原因.请参阅此问题,了解可能的选项(我没有尝试任何选项):TabControl 中的轨迹栏背景.

Make the hosted control transparent, so the toolstrip's background shows through. This will not work for TrackBar as it doesn't support transparent background, for some reason. See this question, for possible options (I didn't try any of them): Trackbar Background in a TabControl.

覆盖轨迹栏的 OnPaint 并用渐变填充它,使其与工具条的背景融合.这听起来有问题,但可行.

Override track bar's OnPaint and fill it with a gradient, so that it blends in with a tool strip's background. This sounds problematic, but doable.

这篇关于Winforms ToolStrip.BackColor 返回错误的颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 14:13