在自定义控件上发布绘图圆角

Issue Drawing Rounded Corners On Custom Control

我正在尝试创建一个类似于带圆角和边框的长矩形的自定义控件。它还将包含一些文本、一个图标等等,但是当以编程方式添加到我的表单时,我在手动绘制控件时遇到了问题。

代码如下所示:

Option Explicit On
Option Strict On

Imports System.Runtime.InteropServices
Imports Transitions
Imports System.Drawing.Drawing2D

Public Class AlertPanel

    Private m_Radius As Integer
    Private m_BorderWidth As Integer
    Private m_AlertType As AlertType
    Private m_Icon As Image

    ''' <summary>
    ''' Indicates a Radius of the control's corners
    ''' </summary>
    ''' <returns>The corner Radius.</returns>
    Public Property Radius As Integer
        Get
            Return m_Radius
        End Get
        Set(value As Integer)
            m_Radius = value
        End Set
    End Property

    ''' <summary>
    ''' Indicates the width to draw the outer border of the control.
    ''' </summary>
    ''' <returns>The border width.</returns>
    Public Property BorderWidth As Integer
        Get
            Return m_BorderWidth
        End Get
        Set(value As Integer)
            m_BorderWidth = value
        End Set
    End Property

    ''' <summary>
    ''' Indicates the type of Alert for the control.
    ''' </summary>
    ''' <returns>The Alert type.</returns>
    Public Property AlertType As AlertType
        Get
            Return m_AlertType
        End Get
        Set(value As AlertType)
            m_AlertType = value
        End Set
    End Property

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.

    End Sub

    Private Sub AlertPanel_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
        Dim rect As Rectangle = Me.ClientRectangle 'Drawing Rounded Rectangle
        rect.X = rect.X + 1
        rect.Y = rect.Y + 1
        rect.Width -= 2
        rect.Height -= 2

        Using bb As GraphicsPath = GetPath(rect, Radius)
            'Draw the background
            Using br As Brush = New SolidBrush(BackColor)
                e.Graphics.SmoothingMode = SmoothingMode.HighQuality
                e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic
                e.Graphics.FillPath(br, bb)
            End Using
            'Draw the border
            Using br As Brush = New SolidBrush(ForeColor)
                rect.Inflate(-1, -1)
                e.Graphics.SmoothingMode = SmoothingMode.HighQuality
                e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic
                e.Graphics.DrawPath(New Pen(br, BorderWidth), bb)
            End Using
        End Using
    End Sub

    Protected Function GetPath(ByVal rc As Rectangle, ByVal r As Int32) As GraphicsPath
        Dim x As Int32 = rc.X, y As Int32 = rc.Y, w As Int32 = rc.Width, h As Int32 = rc.Height
        r = r << 1
        Dim path As GraphicsPath = New GraphicsPath()
        If r > 0 Then
            If (r > h) Then r = h
            If (r > w) Then r = w
            path.AddArc(x, y, r, r, 180, 90)
            path.AddArc(x + w - r, y, r, r, 270, 90)
            path.AddArc(x + w - r, y + h - r, r, r, 0, 90)
            path.AddArc(x, y + h - r, r, r, 90, 90)
            path.CloseFigure()
        Else
            path.AddRectangle(rc)
        End If
        Return path
    End Function

End Class

然后我这样称呼它:

Dim a As New AlertPanel
            With a
                .Size = New Size(400, 60)
                .Location = New Point(100, 200)
                .AlertType = AlertType.Major
                .ForeColor = Color.Black
                .BorderWidth = 1
                .BackColor = Color.IndianRed
                .Radius = 10
            End With
            Me.Controls.Add(a)

我还剩下这个:

更新

根据下面的 Plutonix 对我的代码进行一些编辑后,我现在得到以下结果:

最终更新

最终结果如下所示。非常感谢 Plutonix 的所有帮助!

I am trying to create a custom control 你没有说这是子类化控件(如 Panel)还是构建为 UserControl。我猜测后者基于 InitializeComponent().

最主要的似乎是 UserControl 的标准边框仍在绘制中。添加此以将其关闭:

Public Sub New()
    MyBase.BorderStyle = Windows.Forms.BorderStyle.None
    ...

您可能希望隐藏 属性 以便最终用户无法在“属性”中将其重新打开。

此外,如果边框较宽,您会发现底部边框被裁剪了一个像素(在您的图像中有些明显 - 顶部水平线看起来比底部边框粗)。将此添加到您的 GetPath 方法中:

h As Int32 = rc.Height - 1

结果:

此外,BackColor被继承并应用于整个客户区,仍然是一个矩形。您可能还需要更换它。将实际的 BackColor 保留为 Transparent,也许还对用户隐藏 属性,并使用新的 FillColor 属性:

' in the paint event
Using br As Brush = New SolidBrush(FillColor)
   ...

使用 FillColor 属性 并强制 BackColorTransparent:

Public Sub ctrlCornerBorder(ctrl As Control, CurveSize As Integer)

    Try

        Dim p As New System.Drawing.Drawing2D.GraphicsPath

        p.StartFigure()
        p.AddArc(New Rectangle(0, 0, CurveSize, CurveSize), 180, 90)
        'p.AddLine(CurveSize, 0, ctrl.Width - CurveSize, 0)

        p.AddArc(New Rectangle(ctrl.Width - CurveSize, 0, CurveSize, CurveSize), -90, 90)
        'p.AddLine(ctrl.Width, CurveSize, ctrl.Width, ctrl.Height - CurveSize)

        p.AddArc(New Rectangle(ctrl.Width - CurveSize, ctrl.Height - CurveSize, CurveSize, CurveSize), 0, 90)
        'p.AddLine(ctrl.Width - 40, ctrl.Height, 40, ctrl.Height)

        p.AddArc(New Rectangle(0, ctrl.Height - CurveSize, CurveSize, CurveSize), 90, 90)
        p.CloseFigure()

        ctrl.Region = New Region(p)
        p.Dispose()

    Catch ex As Exception
        MsgBox(Err.Number & vbCrLf & Err.Description, MsgBoxStyle.Information)
    End Try

将此作为 Class 文件并按如下方式调用...

ctrlCornerBorder(pnlList, 15).

这里的 ctrlCornerBorder 是我们的 Class 文件名和 pnlList 作为我们的面板名称 15 是根据您的需要在面板上制作弯曲边缘的值...

我使用绘制事件期间调用的函数在按钮控件上设置了圆角。

  1. 必须有visual studio,创建一个新项目
  2. Select 一个新的 windows 表单作为您的新项目
  3. 向表单添加 2 个按钮
  4. 双击表格任意位置打开代码window
  5. 删除所有代码,包括 Form1 子 headers,并粘贴到下面


Imports System.Drawing.Drawing2D


Public Class Form1

    Public Sub buttonBorderRadius(ByRef buttonObj As Object, ByVal borderRadiusINT As Integer)
        Dim p As New Drawing2D.GraphicsPath()
        p.StartFigure()
        'TOP LEFT CORNER
        p.AddArc(New Rectangle(0, 0, borderRadiusINT, borderRadiusINT), 180, 90)
        p.AddLine(40, 0, buttonObj.Width - borderRadiusINT, 0)
        'TOP RIGHT CORNER
        p.AddArc(New Rectangle(buttonObj.Width - borderRadiusINT, 0, borderRadiusINT, borderRadiusINT), -90, 90)
        p.AddLine(buttonObj.Width, 40, buttonObj.Width, buttonObj.Height - borderRadiusINT)
        'BOTTOM RIGHT CORNER
        p.AddArc(New Rectangle(buttonObj.Width - borderRadiusINT, buttonObj.Height - borderRadiusINT, borderRadiusINT, borderRadiusINT), 0, 90)
        p.AddLine(buttonObj.Width - borderRadiusINT, buttonObj.Height, borderRadiusINT, buttonObj.Height)
        'BOTTOM LEFT CORNER
        p.AddArc(New Rectangle(0, buttonObj.Height - borderRadiusINT, borderRadiusINT, borderRadiusINT), 90, 90)
        p.CloseFigure()
        buttonObj.Region = New Region(p)
    End Sub



    Private Sub Button1_Paint(sender As Object, e As PaintEventArgs) Handles Button1.Paint
        buttonBorderRadius(sender, 25)
    End Sub

    Private Sub Button2_Paint(sender As Object, e As PaintEventArgs) Handles Button2.Paint
        buttonBorderRadius(sender, 50)
    End Sub


End Class

调用函数buttonBorderRadius(sender, 50)意味着您可以为各个按钮设置不同的borderRadius。 因为它使用 object,您可以将相同的功能应用于图片框和其他控件(虽然不是全部)。

因此您可以使用 buttonBorderRadius(sender, 10) 设置 10 像素的边框半径 和像这样的 50 像素半径 buttonBorderRadius(sender, 50) 只需将整数更改为函数中的第二个参数, 第一个参数必须是 object 变量。