Групповой блок Winforms с цветной рамкой

Я использовал следующий код для создания группового блока с цветными рамками:

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

Проблема в том, что он находится внутри прокручиваемого контейнера, и если он прокручивается, граница перерисовывается неправильно:

Перерисовка

3 ответа

Решение

Вы можете заставить его плохо себя вести:

введите описание изображения здесь

Это идет не так, потому что ваш код использует e.ClipRectangle. Обратите внимание, что он появляется дважды в вашем фрагменте. Эта переменная не дает вам прямоугольник границы. Он говорит вам, сколько из вашей клиентской области необходимо перерисовать. Это возможность оптимизации, вы можете рисовать меньше, опуская части клиентской области, которые не нужно обновлять.

Как правило, он имеет такой же размер, как и прямоугольник дисплея, поэтому он выглядел так, как будто работал нормально. Но не тогда, когда вы помещаете его в прокручиваемый контейнер, Windows оптимизирует прокрутки, разбивая части клиентской области, которые просто могут быть перемещены. И затем генерирует краску для частей, которые обнаруживаются свитком. С маленьким e.ClipRectangle. Вы можете видеть это на скриншоте, обратите внимание на маленькие прямоугольники.

Замените e.ClipRectangle на Me.DisplayRectangle.

Этот класс позволяет устанавливать границы для всех ваших блоков или индивидуально, добавляя элемент управления цветом границы на вкладку свойств для группового блока.

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

Вы должны использовать Me.ClientRectangle вместо Me.DisplayRectangle для бодера и текста. Если вы используете старый способ, то проблема мерцания не решается, и текст группового поля не будет отображаться.

Другие вопросы по тегам