在自定义控件上发出绘制圆角

时间:2015-04-20 12:08:17

标签: .net vb.net user-controls paint rounded-corners

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

代码如下:

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)

我留下了这个:

enter image description here

更新

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

enter image description here

最终更新

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

enter image description here

3 个答案:

答案 0 :(得分:2)

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

结果:

enter image description here

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

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

使用FillColor属性并强制BackColorTransparent

enter image description here

答案 1 :(得分:0)

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

将此作为一个类文件并调用Like This as Follows ...

ctrlCornerBorder(pnlList,15)。

这里ctrlCornerBorder是我们的类文件名和pnlList因为我们的面板名称和15是根据你需要在面板上制作曲线边缘而改变的值...

答案 2 :(得分:0)

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

  1. 必须拥有visual studio,创建一个新项目
  2. 选择新窗体作为新项目
  3. 在表单中添加2个x按钮
  4. 双击表单上的任意位置以打开代码窗口
  5. 删除所有代码,包括Form1子标题,然后粘贴到下面的

  6. 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。 因为它使用了对象,你可以将相同的功能应用于图片框和其他控件(不是全部)。

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