如何使用WinForms (.NET)绘制圆角矩形?

18

使用C#绘制矩形,需要在每个边缘绘制弧线。首先绘制矩形,然后点击按钮,在边缘处绘制弧线。我该如何实现?


6个回答

24

C#中的Graphics类没有内置方法来绘制圆角矩形,但是有几种方法可以实现这个效果。在Jay Riggs回答中提供了一些好的建议,此外我建议您查看这篇文章:

使用GraphicsPath创建C#圆角矩形

首先,我们创建一个GraphicsPath,然后调用StartFigure以开始向路径添加边缘。这段代码的其余部分是为了绘制圆角矩形的左上角和顶部线条。如果我们需要将这个角落变成圆角,则添加一个弧-否则...


太棒了!这对我帮助很大。 - ChandlerPelhams
9
该链接已失效,答案需要修改。 - Broots Waymb
@TomNeyland,我会检查Jay Riggs答案中的链接。我使用了第一个链接中的代码,它非常好用! - Broots Waymb
1
以下是一个可工作的链接版本,以防其他人找到此页面:https://web.archive.org/web/20121102092054/http://www.switchonthecode.com/tutorials/csharp-creating-rounded-rectangles-using-a-graphics-path - Bluecakes
不要忘记查看Luis Dragotto 04/03/2010 - 15:23的评论。在我的情况下,我需要遵循他的建议才能使结果可接受。 - JRB
显示剩余2条评论

22

4
那个第一个链接(圆角矩形,字体测量……)非常棒。点击“下载源代码”可以获得一套很棒的扩展方法,可以从Graphics库中调用(例如FillRoundedRectangle和DrawRoundedRectangle)。这是一篇很好的文章,但你实际上只需要下载其中的一个.cs文件即可。 - Lee Richardson
那个第一个链接太棒了!正是我所需要的。 - Broots Waymb

2
我知道这篇文章已经有点老了,但是当搜索如何在C#中创建圆角矩形时,它是排名最高的。我使用代码中的AddArc方法不准确,因此如果你使用接受答案的代码,你会得到一个奇怪的圆角矩形。左上角是正确的,右上角和左下角是变形的,并且右下角太小了。我已经调整了代码中的一些内容来弥补AddArc的不准确性,我相信我已经有了一个有效的解决方案来创建一个正确的圆角矩形。这个版本还可以将矩形分成左上角和右下角两个部分,为3D效果进行浅色/深色阴影处理非常方便。

设置窗口区域以及创建用于追踪浅色和深色笔进行阴影处理的左上角/右下角路径的示例用法:

        Region = new Region(RoundedRectangles.RoundedRectangle.Create(new Rectangle(0, 0, Size.Width, Size.Height), 8, RoundedRectangles.RoundedRectangle.RectangleCorners.TopRight | RoundedRectangles.RoundedRectangle.RectangleCorners.TopLeft));
        TopLeftPath = RoundedRectangles.RoundedRectangle.Create(new Rectangle(0, 0, Size.Width, Size.Height), 8, RoundedRectangles.RoundedRectangle.RectangleCorners.TopRight | RoundedRectangles.RoundedRectangle.RectangleCorners.TopLeft, RoundedRectangles.RoundedRectangle.WhichHalf.TopLeft);
        BottomRightPath = RoundedRectangles.RoundedRectangle.Create(new Rectangle(0, 0, Size.Width-1, Size.Height-1), 8, RoundedRectangles.RoundedRectangle.RectangleCorners.TopRight | RoundedRectangles.RoundedRectangle.RectangleCorners.TopLeft, RoundedRectangles.RoundedRectangle.WhichHalf.BottomRight);

最后,这是代码:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace RoundedRectangles
{
public abstract class RoundedRectangle
{
    [Flags]
    public enum RectangleCorners
    {
        None = 0, TopLeft = 1, TopRight = 2, BottomLeft = 4, BottomRight = 8,
        All = TopLeft | TopRight | BottomLeft | BottomRight
    }

    public enum WhichHalf
    {
        TopLeft,
        BottomRight,
        Both
    }

    static void Corner(GraphicsPath path, int x1, int y1, int x2, int y2, int x3, int y3)
    {
        path.AddLine(x1, y1, x2, y2);
        path.AddLine(x2, y2, x3, y3);
    }

    public static GraphicsPath Create(int x, int y, int width, int height, int radius, RectangleCorners corners, WhichHalf half)
    {
        if (radius <= 0)
        {
            GraphicsPath rectp = new GraphicsPath();
            rectp.AddRectangle(new Rectangle(x, y, width, height));
            return rectp;
        }

        int dia = radius * 2;

        Rectangle TLarc = new Rectangle(x, y, dia, dia);
        Rectangle TRarc = new Rectangle(x + width - dia - 1, y, dia, dia);
        Rectangle BRarc = new Rectangle(x + width - dia - 1, y + height - dia - 1, dia, dia);
        Rectangle BLarc = new Rectangle(x, y + height - dia - 1, dia, dia);

        Rectangle TLsquare = new Rectangle(x, y, radius, radius);
        Rectangle TRsquare = new Rectangle(x + width - radius, y, radius, radius);
        Rectangle BRsquare = new Rectangle(x + width - radius, y + height - radius, radius, radius);
        Rectangle BLsquare = new Rectangle(x, y + height - radius, radius, radius);

        GraphicsPath p = new GraphicsPath();
        p.StartFigure();

        if (half == WhichHalf.Both || half == WhichHalf.TopLeft)
        {
            if (corners.HasFlag(RectangleCorners.BottomLeft))
                p.AddArc(BLarc, 135, 45);
            else
                p.AddLine(BLsquare.Left, BLsquare.Bottom, BLsquare.Left, BLsquare.Top);

            p.AddLine(BLsquare.Left, BLsquare.Top - 1, TLsquare.Left, TLsquare.Bottom + 1);

            if (corners.HasFlag(RectangleCorners.TopLeft))
                p.AddArc(TLarc, 180, 90);
            else
                Corner(p, TLsquare.Left, TLsquare.Bottom, TLsquare.Left, TLsquare.Top, TLsquare.Right, TLsquare.Top);

            p.AddLine(TLsquare.Right + 1, TLsquare.Top, TRsquare.Left - 1, TRsquare.Top);

            if (corners.HasFlag(RectangleCorners.TopRight))
                p.AddArc(TRarc, -90, 45);
        }

        if (half == WhichHalf.Both || half == WhichHalf.BottomRight)
        {
            if (corners.HasFlag(RectangleCorners.TopRight))
                p.AddArc(TRarc, -45, 45);
            else
                p.AddLine(TRsquare.Right, TRsquare.Top, TRsquare.Right, TRsquare.Bottom);

            p.AddLine(TRsquare.Right, TRsquare.Bottom + 1, BRsquare.Right, BRsquare.Top - 1);

            if (corners.HasFlag(RectangleCorners.BottomRight))
                p.AddArc(BRarc, 0, 90);
            else
                Corner(p, BRsquare.Right, BRsquare.Top, BRsquare.Right, BRsquare.Bottom, BRsquare.Left, BRsquare.Bottom);

            p.AddLine(BRsquare.Left - 1, BRsquare.Bottom, BLsquare.Right + 1, BLsquare.Bottom);

            if (corners.HasFlag(RectangleCorners.BottomLeft))
                p.AddArc(BLarc, 90, 45);
            else
                p.AddLine(BLsquare.Right, BLsquare.Bottom, BLsquare.Left, BLsquare.Bottom);
        }

        return p;
    }

    public static GraphicsPath Create(Rectangle rect, int radius, RectangleCorners c, WhichHalf which_half)
    { return Create(rect.X, rect.Y, rect.Width, rect.Height, radius, c, which_half); }

    public static GraphicsPath Create(Rectangle rect, int radius, RectangleCorners c)
    { return Create(rect.X, rect.Y, rect.Width, rect.Height, radius, c, WhichHalf.Both); }

    public static GraphicsPath Create(Rectangle rect, int radius)
    { return Create(rect.X, rect.Y, rect.Width, rect.Height, radius, RectangleCorners.All, WhichHalf.Both); }

}

}


0

首先画出四条线,然后在四个角落处画弧线。


0

以上所有内容都适用于绘图,但如果您想将图形路径转换为自定义控件的区域,我认为您应该使用CreateRoundRectRgn函数(来自gdi32)以获得顶部右侧、底部左侧和底部右侧边缘的正确曲线(根据半径正确绘制了左上角边缘)。快速查看http://pages.citebite.com/e1u2t5b7t4bih(来自instanceofTom的答案的网站)。


0
使用Pen的LineJoin属性。
Pen myPen = new Pen(Brushes.Black);

myPen.Width = 8.0f;

// Set the LineJoin property
myPen.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;

// Draw the rectangle
e.Graphics.DrawRectangle(myPen, new Rectangle(50, 50, 200, 200));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接