Results 1 to 4 of 4

Thread: Round Corner Rectangle

  1. #1

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Posts
    12,397

    Round Corner Rectangle

    Features
    Draws or fills a rectangle with rounded corners using GDI+.

    Drawbacks
    None.

    Plans
    None.

    Source
    Code:
    Option Strict On
    Option Explicit On
    
    Imports System.Runtime.CompilerServices
    Module ExtendedGraphics
    
        ''' <summary>
        ''' Draws a rectangle with it's corners rounded using GDI+
        ''' </summary>
        ''' <param name="g">The graphics that does the drawing</param>
        ''' <param name="pen">System.Drawing.Pen that determines the color, width, and style of the rectangle.</param>
        ''' <param name="area">System.Drawing.Rectangle that represents the rectangle to draw.</param>
        ''' <param name="radius">System.Int32 that determines the roundness of the corners.</param>
        <Extension()>
        Public Sub DrawRectangle(ByVal g As Graphics, ByVal pen As Pen, ByVal area As Rectangle, ByVal radius As Int32)
            'Clip out the corners
            g.SetClip(New Rectangle(area.Location, New Size(radius, radius)), Drawing2D.CombineMode.Exclude) 'upper-left
            g.SetClip(New Rectangle(New Point(area.Right - radius, area.Top), New Size(radius * 2, radius)), Drawing2D.CombineMode.Exclude) 'upper-right
            g.SetClip(New Rectangle(New Point(area.Left, area.Bottom - radius), New Size(radius, radius * 2)), Drawing2D.CombineMode.Exclude) 'lower-left
            g.SetClip(New Rectangle(New Point(area.Right - radius, area.Bottom - radius), New Size(radius * 2, radius * 2)), Drawing2D.CombineMode.Exclude) 'lower-right
    
            'Draw the initial rectangle
            g.DrawRectangle(pen, area)
            g.ResetClip()
    
            'Draw the corners
            g.DrawArc(pen, area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
            g.DrawArc(pen, area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
            g.DrawArc(pen, area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
            g.DrawArc(pen, area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
        End Sub
    
        ''' <summary>
        ''' Draws a rectangle with it's corners rounded using GDI+
        ''' </summary>
        ''' <param name="g">The graphics that does the drawing</param>
        ''' <param name="pen">System.Drawing.Pen that determines the color, width, and style of the rectangle.</param>
        ''' <param name="location">The x and y coordinates that determine the upper-left corner of the rectangle.</param>
        ''' <param name="size">The width and height that determine the size of the rectangle.</param>
        ''' <param name="radius">System.Int32 that determines the roundness of the corners.</param>
        <Extension()>
        Public Sub DrawRectangle(ByVal g As Graphics, ByVal pen As Pen, ByVal location As Point, ByVal size As Size, ByVal radius As Int32)
            'Create a rectangle
            Dim area As Rectangle = New Rectangle(location, size)
    
            'Clip out the corners
            g.SetClip(New Rectangle(area.Location, New Size(radius, radius)), Drawing2D.CombineMode.Exclude) 'upper-left
            g.SetClip(New Rectangle(New Point(area.Right - radius, area.Top), New Size(radius * 2, radius)), Drawing2D.CombineMode.Exclude) 'upper-right
            g.SetClip(New Rectangle(New Point(area.Left, area.Bottom - radius), New Size(radius, radius * 2)), Drawing2D.CombineMode.Exclude) 'lower-left
            g.SetClip(New Rectangle(New Point(area.Right - radius, area.Bottom - radius), New Size(radius * 2, radius * 2)), Drawing2D.CombineMode.Exclude) 'lower-right
    
            'Draw the initial rectangle
            g.DrawRectangle(pen, area)
            g.ResetClip()
    
            'Draw the corners
            g.DrawArc(pen, area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
            g.DrawArc(pen, area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
            g.DrawArc(pen, area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
            g.DrawArc(pen, area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
        End Sub
    
        ''' <summary>
        ''' Draws a rectangle with it's corners rounded using GDI+
        ''' </summary>
        ''' <param name="g">The graphics that does the drawing</param>
        ''' <param name="pen">System.Drawing.Pen that determines the color, width, and style of the rectangle.</param>
        ''' <param name="x">The x coordinate that determines the upper-left corner of the rectangle.</param>
        ''' <param name="y">The y coordinate that determines the upper-left corner of the rectangle.</param>
        ''' <param name="width">Width of the rectangle to draw.</param>
        ''' <param name="height">Height of the rectangle to draw.</param>
        ''' <param name="radius">System.Int32 that determines the roundness of the corners.</param>
        <Extension()>
        Public Sub DrawRectangle(ByVal g As Graphics, ByVal pen As Pen, ByVal x As Int32, ByVal y As Int32, ByVal width As Int32, ByVal height As Int32, ByVal radius As Int32)
            'Create a rectangle
            Dim area As Rectangle = New Rectangle(x, y, width, height)
    
            'Clip out the corners
            g.SetClip(New Rectangle(area.Location, New Size(radius, radius)), Drawing2D.CombineMode.Exclude) 'upper-left
            g.SetClip(New Rectangle(New Point(area.Right - radius, area.Top), New Size(radius * 2, radius)), Drawing2D.CombineMode.Exclude) 'upper-right
            g.SetClip(New Rectangle(New Point(area.Left, area.Bottom - radius), New Size(radius, radius * 2)), Drawing2D.CombineMode.Exclude) 'lower-left
            g.SetClip(New Rectangle(New Point(area.Right - radius, area.Bottom - radius), New Size(radius * 2, radius * 2)), Drawing2D.CombineMode.Exclude) 'lower-right
    
            'Draw the initial rectangle
            g.DrawRectangle(pen, area)
            g.ResetClip()
    
            'Draw the corners
            g.DrawArc(pen, area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
            g.DrawArc(pen, area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
            g.DrawArc(pen, area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
            g.DrawArc(pen, area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
        End Sub
    
        ''' <summary>
        ''' Fills a rectangle with it's corners rounded using GDI+
        ''' </summary>
        ''' <param name="g">The graphics that does the drawing</param>
        ''' <param name="brush">System.Drawing.Brush that determines the color and style of the line.</param>
        ''' <param name="area">System.Drawing.Rectangle that represents the rectangle to fill.</param>
        ''' <param name="radius">System.Int32 that determines the roundness of the corners.</param>
        <Extension()>
        Public Sub FillRectangle(ByVal g As Graphics, ByVal brush As Brush, ByVal area As Rectangle, ByVal radius As Int32)
            Dim path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
    
            'Add the corners
            path.AddArc(area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
            path.AddArc(area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
            path.AddArc(area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
            path.AddArc(area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
    
            'Fill the rounded rectangle
            g.FillPath(brush, path)
        End Sub
    
        ''' <summary>
        ''' Fills a rectangle with it's corners rounded using GDI+
        ''' </summary>
        ''' <param name="g">The graphics that does the drawing</param>
        ''' <param name="brush">System.Drawing.Pen that determines the color and style of the rectangle.</param>
        ''' <param name="location">The x and y coordinates that determine the upper-left corner of the rectangle.</param>
        ''' <param name="size">The width and height that determine the size of the rectangle.</param>
        ''' <param name="radius">System.Int32 that determines the roundness of the corners.</param>
        <Extension()>
        Public Sub FillRectangle(ByVal g As Graphics, ByVal brush As Brush, ByVal location As Point, ByVal size As Size, ByVal radius As Int32)
            Dim area As Rectangle = New Rectangle(location, size)
            Dim path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
    
            'Add the corners
            path.AddArc(area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
            path.AddArc(area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
            path.AddArc(area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
            path.AddArc(area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
    
            'Fill the rounded rectangle
            g.FillPath(brush, path)
        End Sub
    
        ''' <summary>
        ''' Fills a rectangle with it's corners rounded using GDI+
        ''' </summary>
        ''' <param name="g">The graphics that does the drawing</param>
        ''' <param name="brush">System.Drawing.Pen that determines the color and style of the rectangle.</param>
        ''' <param name="x">The x coordinate that determines the upper-left corner of the rectangle.</param>
        ''' <param name="y">The y coordinate that determines the upper-left corner of the rectangle.</param>
        ''' <param name="width">Width of the rectangle to draw.</param>
        ''' <param name="height">Height of the rectangle to draw.</param>
        ''' <param name="radius">System.Int32 that determines the roundness of the corners.</param>
        <Extension()>
        Public Sub FillRectangle(ByVal g As Graphics, ByVal brush As Brush, ByVal x As Int32, ByVal y As Int32, ByVal width As Int32, ByVal height As Int32, ByVal radius As Int32)
            Dim area As Rectangle = New Rectangle(x, y, width, height)
            Dim path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
    
            'Add the corners
            path.AddArc(area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
            path.AddArc(area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
            path.AddArc(area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
            path.AddArc(area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
    
            'Fill the rounded rectangle
            g.FillPath(brush, path)
        End Sub
    
    End Module
    Notes
    To use the code, follow these simple instructions:
    1. Add a new Module to your project
    2. Name the Module ExtendedGraphics
    3. Delete any auto-generated code
    4. Paste the source code into the Module


    Example
    Here is an example of creating a solid black rectangle with rounded edges:
    Code:
    'In a control's Paint event
    e.Graphics.FillRectangle(Brushes.Black, 5, 5, 500, 500, 50)
    Image
    Name:  round rectangle.png
Views: 5166
Size:  2.6 KB
    Last edited by dday9; Dec 5th, 2014 at 01:23 PM.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | HtmlLessons | CssLessons | Code Tags | Sword of Fury - Jameram

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,598

    Re: Round Corner Rectangle

    Quote Originally Posted by dday9 View Post
    ...
    Drawbacks
    Fill does not render semi-transparent colors properly.
    ...
    If you did your graphics path in the correct order, going around the rectangle, you wouldn't need the clipping and rectangle fill, and your translucent colors would work properly.

    For example, the FillRectangle sub used by your example call:
    Instead of this
    Code:
      Public Sub FillRectangle(ByVal g As Graphics, ByVal brush As Brush, ByVal x As Int32, ByVal y As Int32, ByVal width As Int32, ByVal height As Int32, ByVal radius As Int32)
        Dim area As Rectangle = New Rectangle(x, y, width, height)
        Dim path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
    
        'Clip out the corners
        g.SetClip(New Rectangle(area.Location, New Size(radius, radius)), Drawing2D.CombineMode.Exclude) 'upper-left
        g.SetClip(New Rectangle(New Point(area.Right - radius, area.Top), New Size(radius * 2, radius)), Drawing2D.CombineMode.Exclude) 'upper-right
        g.SetClip(New Rectangle(New Point(area.Left, area.Bottom - radius), New Size(radius, radius * 2)), Drawing2D.CombineMode.Exclude) 'lower-left
        g.SetClip(New Rectangle(New Point(area.Right - radius, area.Bottom - radius), New Size(radius * 2, radius * 2)), Drawing2D.CombineMode.Exclude) 'lower-right
    
        'Fill the initial rectangle
        g.FillRectangle(brush, area)
        g.ResetClip()
    
    
        'Add the corners
        path.AddArc(area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
        path.AddArc(area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
        path.AddArc(area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
        path.AddArc(area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
    
        'Fill the corners
        g.FillPath(brush, path)
      End Sub
    It should be this
    Code:
      Public Sub FillRectangle(ByVal g As Graphics, ByVal brush As Brush, ByVal x As Int32, ByVal y As Int32, ByVal width As Int32, ByVal height As Int32, ByVal radius As Int32)
        Dim area As Rectangle = New Rectangle(x, y, width, height)
        Dim path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
    
        'Add the corners
        path.AddArc(area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
        path.AddArc(area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
        path.AddArc(area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
        path.AddArc(area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
    
        'Fill the rounded rectangle
        g.FillPath(brush, path)
      End Sub
    Just swap the two bottom lines of your AddArcs so you go around the rectangle, topLeft, topRight, bottomRight, bottomLeft.
    (and changed the "Fill the rounded corners" comment.)
    p.s. Your black rectangle example shows as green in my browser

    Code:
      Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Using gpBrush As New SolidBrush(Color.FromArgb(64, Color.Red))
          e.Graphics.FillRectangle(Brushes.White, 10, 10, 500, 500, 75)
          e.Graphics.FillRectangle(gpBrush, 20, 20, 420, 420, 75)
          e.Graphics.FillRectangle(gpBrush, 80, 80, 420, 420, 75)
        End Using
      End Sub
    Attached Images Attached Images  
    Last edited by passel; Dec 5th, 2014 at 02:15 PM.

  3. #3

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Posts
    12,397

    Re: Round Corner Rectangle

    Awesome, thank you so much for the improvements passel.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | HtmlLessons | CssLessons | Code Tags | Sword of Fury - Jameram

  4. #4
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,598

    Re: Round Corner Rectangle

    I see you updated the Fills, the Draws should be done in a similar fashion.
    For an example, I just changed the Draw sub with the same parameters (except Pen instead of Brush), and copied the code from the analogous Fill sub, just changing the FillPath to DrawPath and brush to pen (and the comment from Fill to Draw). The only addition was the line to close the figure so it draws the last side to close the rectangle.
    Code:
      Public Sub DrawRectangle(ByVal g As Graphics, ByVal pen As Pen, ByVal x As Int32, ByVal y As Int32, ByVal width As Int32, ByVal height As Int32, ByVal radius As Int32)
        'Create a rectangle
        Dim area As Rectangle = New Rectangle(x, y, width, height)
        Dim path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
    
        'Add the corners
        path.AddArc(area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
        path.AddArc(area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
        path.AddArc(area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
        path.AddArc(area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
        path.CloseAllFigures()
    
        'Draw the rounded rectangle
        g.DrawPath(pen, path)
      End Sub
    Last edited by passel; Dec 5th, 2014 at 02:34 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width