Search code examples
c#winformsgroupbox

Custom GroupBox with round edges


I have a question about UI in visual studio, in C#. I want to make my groupbox custom to look like this:

GROUP BOX DESIGN EXAMPLE

and then, I also want it to expend depends on the user's screen resolution, so the size of the group box isn't fixed, and I need it to be for example 80% of the screen.

So my question is actually two question:

  1. make a groupbox costum
  2. make it 80% (for example) wide of the screen.

EDIT: thanks to this answer: How to make group box text alignment center in win forms? I managed to do what I wanted with the colors, now I am just missing the round corners. any ideas?


Solution

  • As an option you can create a custom control deriving from GroupBox:

    • You need to calculate a round rectangle shape. To do so, as an option you can use AddArc method and add arcs to four corners of a rectangle in a path.
    • To draw header background with hatch style, you can use a HatchBrush. So add a property for title hatch style. This way you can use different HatchStyle values for title back-ground.
    • To have a different title color and title font, add some properties to control.
    • In a more complete implementation, you should implement properties in a way which setting a new value to property cause repainting the control by calling this.Invalidate().
    • To prevent flicker while resizing turn on double buffering by setting DoubleBuffered to true in constructor.
    • To have transparent background in corners, use GroupBoxRenderer.DrawParentBackground. Screenshot

    enter image description here

    Code

    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;
    public class RoundPanel : GroupBox
    {
        public RoundPanel()
        {
            this.DoubleBuffered = true;
            this.TitleBackColor = Color.SteelBlue;
            this.TitleForeColor = Color.White;
            this.TitleFont = new Font(this.Font.FontFamily, Font.Size + 8, FontStyle.Bold);
            this.BackColor = Color.Transparent;
            this.Radious = 25;
            this.TitleHatchStyle = HatchStyle.Percent60;
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            GroupBoxRenderer.DrawParentBackground(e.Graphics, this.ClientRectangle, this);
            var rect = ClientRectangle;
            using (var path = GetRoundRectagle(this.ClientRectangle, Radious))
            {
                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                rect = new Rectangle(0, 0,
                    rect.Width, TitleFont.Height + Padding.Bottom + Padding.Top);
                if(this.BackColor!= Color.Transparent)
                    using (var brush = new SolidBrush(BackColor))
                        e.Graphics.FillPath(brush, path);
                var clip = e.Graphics.ClipBounds;
                e.Graphics.SetClip(rect);
                using (var brush = new HatchBrush(TitleHatchStyle,
                    TitleBackColor, ControlPaint.Light(TitleBackColor)))
                    e.Graphics.FillPath(brush, path);
                using (var pen = new Pen(TitleBackColor, 1))
                    e.Graphics.DrawPath(pen, path);
                TextRenderer.DrawText(e.Graphics, Text, TitleFont, rect, TitleForeColor);
                e.Graphics.SetClip(clip);
                using (var pen = new Pen(TitleBackColor, 1))
                    e.Graphics.DrawPath(pen, path);
            }
        }
        public Color TitleBackColor { get; set; }
        public HatchStyle TitleHatchStyle { get; set; }
        public Font TitleFont { get; set; }
        public Color TitleForeColor { get; set; }
        public int Radious { get; set; }
        private GraphicsPath GetRoundRectagle(Rectangle b, int r)
        {
            GraphicsPath path = new GraphicsPath();
            path.AddArc(b.X, b.Y, r, r, 180, 90);
            path.AddArc(b.X + b.Width - r - 1, b.Y, r, r, 270, 90);
            path.AddArc(b.X + b.Width - r - 1, b.Y + b.Height - r - 1, r, r, 0, 90);
            path.AddArc(b.X, b.Y + b.Height - r - 1, r, r, 90, 90);
            path.CloseAllFigures();
            return path;
        }
    }