【问题标题】:Show a Label with semi-transparent BackColor above other controls?在其他控件上方显示带有半透明背景颜色的标签?
【发布时间】:2016-03-23 22:55:09
【问题描述】:

我有一个自定义控件,其中包含两个动画 图片框控件和一个标签控件他们。

子索引设置为标签始终位于顶部,但图片框会互换,因此在动画时它们每次显示不同的图像。

据我了解,标签需要有一个父控件,它可以支持半透明颜色(Argb)。由于标签将活动图片框作为其父级,因此它也会被动画化,这根本不是我想要的。

有没有办法固定孩子相对于父母父母的位置?

【问题讨论】:

  • 您无法在 WinForms 中实现此效果,因为平台不支持真正的控制变量不透明度。 “透明背景”被实现为使根父级(底层Form)重新绘制其背景的hack。您无法成功地将多个透明控件叠加在顶部。
  • @Dai - 我也这么认为,但希望更好;)。有没有其他方法可以使用win forms达到类似的效果。我见过 DevXpress 的人制作具有类似效果的控件,所以我想尝试一下。任何其他不包含 WPF 或来自 win 表单的解决方案?
  • @Dino 如果我理解你的问题,请告诉我:你需要在你的图片框上方有一个只显示文本的透明标签吗?
  • @Reza Aghaei - 不完全是。我想要动画图片框上的半透明颜色。我想创建类似于 windows tile 的东西。
  • @Dino,你能告诉我们你尝试了什么吗?

标签: c# .net winforms


【解决方案1】:

要拥有透明的标签控件,可以重写OnPaint方法,绘制所有与标签相交的控件,最后绘制标签的背景和文字。

另外在移动图片框的时候,别忘了调用透明标签的Invalidate()方法。

截图

示例实施

public class TransparentLabel : Label
{
    public TransparentLabel()
    {
        this.transparentBackColor = Color.Blue;
        this.opacity = 50;
        this.BackColor = Color.Transparent;
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        if (Parent != null)
        {
            using (var bmp = new Bitmap(Parent.Width, Parent.Height))
            {
                Parent.Controls.Cast<Control>()
                      .Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this))
                      .Where(c => c.Bounds.IntersectsWith(this.Bounds))
                      .OrderByDescending(c => Parent.Controls.GetChildIndex(c))
                      .ToList()
                      .ForEach(c => c.DrawToBitmap(bmp, c.Bounds));


                e.Graphics.DrawImage(bmp, -Left, -Top);
                using (var b = new SolidBrush(Color.FromArgb(this.Opacity, this.TransparentBackColor)))
                {
                    e.Graphics.FillRectangle(b, this.ClientRectangle);
                }
                e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
                TextRenderer.DrawText(e.Graphics, this.Text, this.Font, this.ClientRectangle, this.ForeColor, Color.Transparent);
            }
        }
    }

    private int opacity;
    public int Opacity
    {
        get { return opacity; }
        set
        {
            if (value >= 0 && value <= 255)
                opacity = value;
            this.Invalidate();
        }
    }

    public Color transparentBackColor;
    public Color TransparentBackColor
    {
        get { return transparentBackColor; }
        set
        {
            transparentBackColor = value;
            this.Invalidate();
        }
    }

    [Browsable(false)]
    public override Color BackColor
    {
        get
        {
            return Color.Transparent;
        }
        set
        {
            base.BackColor = Color.Transparent;
        }
    }
}

【讨论】:

  • 要使其背景完全透明,请将不透明度设置为 0。如果您对答案有任何疑问,请告诉我 :)
  • 我会在接下来的几个小时内尝试,当我找到时间并会回复结果。非常感谢。
  • 不客气,感谢您的反馈 :) 截图取自执行,在这里可以正常工作。
  • 我是菜鸟,所以这有点过头了。我实施您的解决方案的方式效果不佳。我知道每次背景发生变化时我都需要在TransparentLabel 上致电Invalidate(),但我有点迷茫,因为这对我来说是全新的。我一直在使用link dot-net-transition 来试验和了解动画,并在此示例项目link 中实现您的解决方案,如所述。最后一个链接是示例项目,因此您可以了解其含义。
  • 您应该在一个简单的测试用例中测试答案,例如以编程方式使用Timer 更改位置和BackGroundPictureBox,您将看到解决方案正常工作。然后您可以尝试将答案应用到您的项目中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多