Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a rounded rectangle at runtime in Windows Forms with VB.NET/C#?

I woud like to create a filled rounded rectangle at run-time and assign it as content of a PictureBox (already created and hidden) in Windows Forms.

Do you have an idea how can I implement it?

like image 845
Drake Avatar asked Jun 26 '09 14:06

Drake


2 Answers

The problem with the fill solution that is marked as the answer is it does not work well with non solid/uniform brushes. Here is another one based on the GraphicsPath class wich I think is more reusable:

public static void FillRoundedRectangle(Graphics graphics, Rectangle rectangle, Brush brush, int radius)
{
    if (graphics == null)
        throw new ArgumentNullException("graphics");

    SmoothingMode mode = graphics.SmoothingMode;
    graphics.SmoothingMode = SmoothingMode.AntiAlias;

    using (GraphicsPath path = RoundedRectangle(rectangle, radius))
    {
        graphics.FillPath(brush, path);
    }
    graphics.SmoothingMode = mode;
}

public static GraphicsPath RoundedRectangle(Rectangle r, int radius)
{
    GraphicsPath path = new GraphicsPath();
    int d = radius * 2;

    path.AddLine(r.Left + d, r.Top, r.Right - d, r.Top);
    path.AddArc(Rectangle.FromLTRB(r.Right - d, r.Top, r.Right, r.Top + d), -90, 90);
    path.AddLine(r.Right, r.Top + d, r.Right, r.Bottom - d);
    path.AddArc(Rectangle.FromLTRB(r.Right - d, r.Bottom - d, r.Right, r.Bottom), 0, 90);
    path.AddLine(r.Right - d, r.Bottom, r.Left + d, r.Bottom);
    path.AddArc(Rectangle.FromLTRB(r.Left, r.Bottom - d, r.Left + d, r.Bottom), 90, 90);
    path.AddLine(r.Left, r.Bottom - d, r.Left, r.Top + d);
    path.AddArc(Rectangle.FromLTRB(r.Left, r.Top, r.Left + d, r.Top + d), 180, 90);
    path.CloseFigure();
    return path;
}

and here is the code for Draw only (not fill), based on the same idea:

public static void DrawRoundedRectangle(Graphics graphics, Rectangle rectangle, Pen pen, int radius)
{
    if (graphics == null)
        throw new ArgumentNullException("graphics");

    SmoothingMode mode = graphics.SmoothingMode;
    graphics.SmoothingMode = SmoothingMode.AntiAlias;

    using (GraphicsPath path = RoundedRectangle(rectangle, radius))
    {
        graphics.DrawPath(pen, path);
    }
    graphics.SmoothingMode = mode;
}
like image 181
Simon Mourier Avatar answered Nov 19 '22 18:11

Simon Mourier


This method fills a rounded rectangle on a graphics object (VB code) :

Public Sub FillRoundedRectangle(ByVal g As Drawing.Graphics, ByVal r As Rectangle, ByVal d As Integer, ByVal b As Brush)
    Dim mode As Drawing2D.SmoothingMode = g.SmoothingMode
    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed
    g.FillPie(b, r.X, r.Y, d, d, 180, 90)
    g.FillPie(b, r.X + r.Width - d, r.Y, d, d, 270, 90)
    g.FillPie(b, r.X, r.Y + r.Height - d, d, d, 90, 90)
    g.FillPie(b, r.X + r.Width - d, r.Y + r.Height - d, d, d, 0, 90)
    g.FillRectangle(b, CInt(r.X + d / 2), r.Y, r.Width - d, CInt(d / 2))
    g.FillRectangle(b, r.X, CInt(r.Y + d / 2), r.Width, CInt(r.Height - d))
    g.FillRectangle(b, CInt(r.X + d / 2), CInt(r.Y + r.Height - d / 2), CInt(r.Width - d), CInt(d / 2))
    g.SmoothingMode = mode
End Sub

To call this function, handle the paint event of the picturebox and pass the e.Graphics object as the first argument, and the picturebox's bounds as the second argument if you want the rectangle to fill your picture box completely.

The d parameter changes the corners' angle, I call it with a value of 30, you can try different values...

Also, here's some code to draw (instead of fill) a rounded rectangle:

Public Sub DrawRoundedRectangle(ByVal g As Drawing.Graphics, ByVal r As Rectangle, ByVal d As Integer, ByVal p As Pen)
    g.DrawArc(p, r.X, r.Y, d, d, 180, 90)
    g.DrawLine(p, CInt(r.X + d / 2), r.Y, CInt(r.X + r.Width - d / 2), r.Y)
    g.DrawArc(p, r.X + r.Width - d, r.Y, d, d, 270, 90)
    g.DrawLine(p, r.X, CInt(r.Y + d / 2), r.X, CInt(r.Y + r.Height - d / 2))
    g.DrawLine(p, CInt(r.X + r.Width), CInt(r.Y + d / 2), CInt(r.X + r.Width), CInt(r.Y + r.Height - d / 2))
    g.DrawLine(p, CInt(r.X + d / 2), CInt(r.Y + r.Height), CInt(r.X + r.Width - d / 2), CInt(r.Y + r.Height))
    g.DrawArc(p, r.X, r.Y + r.Height - d, d, d, 90, 90)
    g.DrawArc(p, r.X + r.Width - d, r.Y + r.Height - d, d, d, 0, 90)
End Sub
like image 10
Meta-Knight Avatar answered Nov 19 '22 18:11

Meta-Knight