Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom GroupBox with custom TextColor, BorderColor and Transparent BackColor

I'm using WinForms. In my form I have a GroupBox. This is a custom group box. I wanted a transparent background for the groupbox. I'm having issues creating a transparent background for the groupbox The problem with this code is i keep on getting an error when i set the group box backcolor to transparent.

Error: Control does not support transparent background colors.

g.Clear(BackColor = Color.Transparent); (This is the line that is giving me the problem)

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

If i do this i get:

This example consists of a Panel with a dice image inside the panel, and the custom Groupbox.

enter image description here

like image 433
taji01 Avatar asked Jan 02 '16 02:01

taji01


1 Answers

The GroupBox control supports transparent background unless you use System as FlatStyle, but for the border color, you need to paint the group box yourself.

You can inherit from GroupBox and then because GroupBox supports Transparent background, so you can simply override the OnPaint and render your group box without doing any thing about background.

Code

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

Screenshot

enter image description here

Some note about the control

  • The GroupBox control supports transparent background unless you use System as FlatStyle.
  • You can also inherit from Panel because is is a container control and also supports transparent back color.
  • If you need to make a custom control that inherits form Control to support transparent background, you should add SetStyle(ControlStyles.SupportsTransparentBackColor, true); in constructor.
  • Above code is based on drawing code of original GroupBox and I made some changes to fit your requirements and also remains like original GroupBox.
  • BorderColor property added to support custom border color.
  • Using ForeColor property of GroupBox to render the title of control may be annoying because ForeColor is an ambient property and will be inherited by child controls. So I created another property like TextColor for this purpose. (Children of group box will use fore color of group box by default, unless you change their fore color property.)
like image 173
Reza Aghaei Avatar answered Sep 29 '22 14:09

Reza Aghaei