Winforms groupbox with colored border

15,221

Solution 1

You can get it to misbehave a lot worse than that:

enter image description here

This goes wrong because of your code using e.ClipRectangle. Note that it appears twice in your snippet. That variable does not give you the border rectangle. It tells you how much of your client area needs to be re-drawn. It is an optimization opportunity, you can draw less by omitting the parts of the client area that don't need to be refreshed.

It is usually the same size as the display rectangle, which is why it looked like it worked just fine. But not when you put it inside a scrollable container, Windows optimizes scrolls by blitting the parts of the client area that simply can be moved. And then generates a paint for the parts that are revealed by the scroll. With a small e.ClipRectangle. You can see that in the screenshot, note the small rectangles.

Replace e.ClipRectangle with Me.DisplayRectangle.

Solution 2

This class allows the border to be set for all of your boxes or individually by adding a border color control to the properties tab for the group box.

Public Class GroupBoxA
    Inherits GroupBox

    Private _borderColor As Color

    Public Sub New()
        MyBase.New()
        Me._borderColor = Color.OrangeRed
    End Sub

    Public Property BorderColor() As Color
        Get
            Return Me._borderColor
        End Get
        Set(ByVal value As Color)
            Me._borderColor = value
        End Set
    End Property

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        Dim tSize As Size = TextRenderer.MeasureText(Me.Text, Me.Font)
        Dim borderRect As Rectangle = Me.DisplayRectangle

        borderRect.Y = (borderRect.Y + (tSize.Height / 2))
        borderRect.Height = (borderRect.Height - (tSize.Height / 2))

        ControlPaint.DrawBorder(e.Graphics, borderRect, Me._borderColor,
                                ButtonBorderStyle.Solid)

        Dim textRect As Rectangle = Me.DisplayRectangle
        textRect.X = (textRect.X + 6)
        textRect.Width = tSize.Width
        textRect.Height = tSize.Height

        e.Graphics.FillRectangle(New SolidBrush(Me.BackColor), textRect)
        e.Graphics.DrawString(Me.Text, Me.Font, New SolidBrush(Me.ForeColor), textRect)
    End Sub
End Class
Share:
15,221

Related videos on Youtube

Matthias
Author by

Matthias

Updated on June 26, 2022

Comments

  • Matthias
    Matthias almost 2 years

    I have used the following code to create a groupbox with colored borders:

    Public Class BorderGroupBox
        Inherits GroupBox
    
        Private _borderColor As Color
        Private _borderWidth As Integer
        Private _borderStyle As ButtonBorderStyle
    
        ...
    
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            Dim tSize As Size = TextRenderer.MeasureText(Me.Text, Me.Font)
            Dim borderRect As Rectangle = e.ClipRectangle
            borderRect.Y = CInt((borderRect.Y + (tSize.Height / 2)))
            borderRect.Height = CInt((borderRect.Height - (tSize.Height / 2)))
            ControlPaint.DrawBorder(e.Graphics, borderRect, _borderColor, _borderWidth, _borderStyle, BorderColor, _borderWidth, _borderStyle, BorderColor, _borderWidth, _borderStyle, BorderColor, _borderWidth, _borderStyle)
            Dim textRect As Rectangle = e.ClipRectangle
            textRect.X = (textRect.X + 6)
            textRect.Width = tSize.Width + 6
            textRect.Height = tSize.Height
            e.Graphics.FillRectangle(New SolidBrush(Me.BackColor), textRect)
            e.Graphics.DrawString(Me.Text, Me.Font, New SolidBrush(Me.ForeColor), textRect)
        End Sub
    End Class
    

    The problem is, it is placed inside a scrollable container, and if it is scrolled the border isn't redrawn correctly:

    Redraw

  • Matthias
    Matthias about 10 years
    I replaced both lines with Me.DisplayRectangle but now it doesnt paint any border at all.
  • user1703401
    user1703401 about 10 years
    I tested it before I posted, using DisplayRectangle worked fine. As it should.
  • Matthias
    Matthias about 10 years
    Did you change anything else in the code? What container did you use?
  • user1703401
    user1703401 about 10 years
    Of course, it is not usable as posted so gave the variables fixed values and added BorderColor. I tested with a plain Panel with a large AutoScrollMinSize.
  • Matthias
    Matthias about 10 years
    It works now, thanks. But the child controls are placed at x=0, y=0 and overlay the border. Is there a way to set the container position?
  • Eddy Jawed
    Eddy Jawed over 6 years
    sorry for silly question, but how do i use this new class on my form to show as a new group box control?
  • Eddy Jawed
    Eddy Jawed over 6 years
    Dim grpNew As New GroupBoxA Controls.Add(grpNew)
  • Magnus
    Magnus almost 5 years
    Me.ClientRectangle solved it all. Me.DisplayRectangle draws the border in the wrong place