具有自定义文本颜色、边框颜色和透明背景颜色的自定义 GroupBox

问题描述 投票:0回答:4

我正在使用

WinForms
。在我的表格中,我有一个
GroupBox
。这是一个 custom 组框。我想要
groupbox
的透明背景。我在为
groupbox
创建透明背景时遇到问题。这段代码的问题是,当我将组框
backcolor
设置为透明时,我不断收到错误。

错误:控件不支持透明背景色。

g.Clear(BackColor = Color.Transparent);
(这是给我带来问题的那行)

    private void DrawGroupBox(GroupBox box, Graphics g, Color textColor, Color borderColor)
    {
        if (box != null)
        {
            Brush textBrush = new SolidBrush(textColor);
            Brush borderBrush = new SolidBrush(borderColor);
            Pen borderPen = new Pen(borderBrush);
            SizeF strSize = g.MeasureString(box.Text, box.Font);
            Rectangle rect = new Rectangle(box.ClientRectangle.X,
                                           box.ClientRectangle.Y + (int)(strSize.Height / 2),
                                           box.ClientRectangle.Width - 1,
                                           box.ClientRectangle.Height - (int)(strSize.Height / 2) - 1);

            // Clear text and border
            g.Clear(BackColor = Color.Transparent);

            // Draw text
            g.DrawString(box.Text, box.Font, textBrush, box.Padding.Left, 0);

            // Drawing Border
            //Left
            g.DrawLine(borderPen, rect.Location, new Point(rect.X, rect.Y + rect.Height));
            //Right
            g.DrawLine(borderPen, new Point(rect.X + rect.Width, rect.Y), new Point(rect.X + rect.Width, rect.Y + rect.Height));
            //Bottom
            g.DrawLine(borderPen, new Point(rect.X, rect.Y + rect.Height), new Point(rect.X + rect.Width, rect.Y + rect.Height));
            //Top1
            g.DrawLine(borderPen, new Point(rect.X, rect.Y), new Point(rect.X + box.Padding.Left, rect.Y));
            //Top2
            g.DrawLine(borderPen, new Point(rect.X + box.Padding.Left + (int)(strSize.Width), rect.Y), new Point(rect.X + rect.Width, rect.Y));
        }
    }

    private void groupBox1_Paint(object sender, PaintEventArgs e)
    {
        GroupBox box = sender as GroupBox;
        DrawGroupBox(box, e.Graphics, Color.Red, Color.Blue);
    }

g.Clear(groupBox1.BackColor = Color.Transparent);

如果我这样做,我会得到:

此示例由

Panel
组成,面板内带有骰子图像, 和定制的
Groupbox

c# .net winforms transparency groupbox
4个回答
9
投票

GroupBox
控件支持透明背景,除非您将
System
用作
FlatStyle
,但对于边框颜色,您需要自己绘制组框。

您可以继承

GroupBox
,然后因为
GroupBox
支持
Transparent
背景,所以您可以简单地覆盖
OnPaint
并渲染您的组框,而不需要对背景做任何事情。

代码

using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
public class GroupBoxEx : GroupBox
{
    private Color borderColor = Color.Black;
    [DefaultValue(typeof(Color), "Black")]
    public Color BorderColor
    {
        get { return borderColor; }
        set { borderColor = value; this.Invalidate(); }
    }
    private Color textColor = Color.Black;
    [DefaultValue(typeof(Color), "Black")]
    public Color TextColor
    {
        get { return textColor; }
        set { textColor = value; this.Invalidate(); }
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        GroupBoxState state = base.Enabled ? GroupBoxState.Normal : 
            GroupBoxState.Disabled;
        TextFormatFlags flags = TextFormatFlags.PreserveGraphicsTranslateTransform | 
            TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.TextBoxControl | 
            TextFormatFlags.WordBreak;
        Color titleColor = this.TextColor;
        if (!this.ShowKeyboardCues) 
            flags |= TextFormatFlags.HidePrefix;
        if (this.RightToLeft == RightToLeft.Yes) 
            flags |= TextFormatFlags.RightToLeft | TextFormatFlags.Right;
        if (!this.Enabled) 
            titleColor = SystemColors.GrayText;
        DrawUnthemedGroupBoxWithText(e.Graphics, new Rectangle(0, 0, base.Width,
            base.Height), this.Text, this.Font, titleColor, flags, state);
        RaisePaintEvent(this, e);
    }
    private void DrawUnthemedGroupBoxWithText(Graphics g, Rectangle bounds, 
        string groupBoxText, Font font, Color titleColor, 
        TextFormatFlags flags, GroupBoxState state)
    {
        Rectangle rectangle = bounds;
        rectangle.Width -= 8;
        Size size = TextRenderer.MeasureText(g, groupBoxText, font, 
            new Size(rectangle.Width, rectangle.Height), flags);
        rectangle.Width = size.Width;
        rectangle.Height = size.Height;
        if ((flags & TextFormatFlags.Right) == TextFormatFlags.Right)
            rectangle.X = (bounds.Right - rectangle.Width) - 8;
        else
            rectangle.X += 8;
        TextRenderer.DrawText(g, groupBoxText, font, rectangle, titleColor, flags);
        if (rectangle.Width > 0)
            rectangle.Inflate(2, 0);
        using (var pen = new Pen(this.BorderColor))
        {
            int num = bounds.Top + (font.Height / 2);
            g.DrawLine(pen, bounds.Left, num - 1, bounds.Left, bounds.Height - 2);
            g.DrawLine(pen, bounds.Left, bounds.Height - 2, bounds.Width - 1,
                bounds.Height - 2);
            g.DrawLine(pen, bounds.Left, num - 1, rectangle.X - 3, num - 1);
            g.DrawLine(pen, rectangle.X + rectangle.Width + 2, num - 1, 
                bounds.Width - 2, num - 1);
            g.DrawLine(pen, bounds.Width - 2, num - 1, bounds.Width - 2,
               bounds.Height - 2);
        }
    }
}

截图

有关控件的一些注意事项

  • GroupBox
    控件支持透明背景,除非您将
    System
    用作
    FlatStyle
  • 你也可以继承
    Panel
    ,因为它是一个容器控件,并且还支持透明背景色。
  • 如果您需要制作一个继承表单
    Control
    的自定义控件来支持透明背景,则应在构造函数中添加
    SetStyle(ControlStyles.SupportsTransparentBackColor, true);
  • 以上代码基于原始
    GroupBox
    的绘图代码,我做了一些更改以满足您的要求,并且仍然像原始
    GroupBox
    一样。
  • 添加
  • BorderColor
    属性以支持自定义边框颜色。
  • 使用
    ForeColor
    GroupBox
    属性来渲染控件的标题可能会很烦人,因为
    ForeColor
    是环境属性,将被子控件继承。因此,我为此目的创建了另一个属性,例如
    TextColor
    。 (组框的子项将默认使用组框的前景色,除非您更改其前景色属性。)

0
投票

尝试这个调整:

在表单的构造函数内:

this.TransparencyKey = Color.Red;

然后在你的代码中:

g.Clear(groupBox1.TransparencyKey = Color.Red);

0
投票

你尝试过SetStyle吗?

public partial class myGroupBox : GroupBox
{
    public TranspBackground()
    {
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    }
}

0
投票

您可以根据需要添加任意数量的 if 语句,就我而言,它工作得非常完美。就用这两个函数我就让它工作了。

private void redrawTransparent() {
    var change = GetAll(this);

    foreach (Control control in change) {
        if (control is System.Windows.Forms.GroupBox groupBox) {
            groupBox.FlatStyle = FlatStyle.Flat;
            groupBox.BackColor = Color.Transparent;
        }
        if(control is System.Windows.Forms.TabPage tabPage) {
            tabPage.BackColor = Color.Transparent;
        }
    }
}

这个函数从表单中获取所有控件。

public static IEnumerable<Control> GetAll(Control control) {
    // Cast the controls collection to IEnumerable<Control>
    var controls = control.Controls.Cast<Control>();

    // Use SelectMany to recursively call GetAll for each nested control and concatenate the results
    return controls.SelectMany(ctrl => GetAll(ctrl)).Concat(controls);
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.