Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
666 views
in Technique[技术] by (71.8m points)

winforms - c# How to make smooth arc region using graphics path

I'm trying to make a label control with rounded sides. Here is my code in OnPaint() overridden method in myclass inherited from Label.

protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
        e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
        e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

        LinearGradientBrush brush = new LinearGradientBrush(this.ClientRectangle, GradientColor1, GradientColor2, 90);
        e.Graphics.FillRectangle(brush, new Rectangle(new Point(0, 0), new Size(this.Width, this.Height)));

        using (GraphicsPath gp = new GraphicsPath())
        {
            gp.AddArc(new Rectangle(new Point(0, 0), new Size(this.Height, this.Height)), 90, 180);
            gp.AddLine(new Point(this.Height / 2, 0), new Point(this.Width - (this.Height / 2), 0));
            gp.AddArc(new Rectangle(new Point(this.Width - this.Height, 0), new Size(this.Height, this.Height)), -90, 180);
            gp.CloseFigure();

            this.Region = new Region(gp);
        }

        base.OnPaint(e);
    }

The problem is that it is not smoothing the curve on the sides and showing the glitches. Here is the screenshot of the control :

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As stated in the comments, you can't anti-alias the region, so you have to use graphic's FillPath method in order for the drawing to be anti-aliased

protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
            e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
            e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

            LinearGradientBrush brush = new LinearGradientBrush(this.ClientRectangle, Color.Aqua, Color.Blue, 90);

            using (GraphicsPath gp = new GraphicsPath())
            {
                gp.AddArc(new Rectangle(new Point(0, 0), new Size(this.Height, this.Height)), 90, 180);
                gp.AddLine(new Point(this.Height / 2, 0), new Point(this.Width - (this.Height / 2), 0));
                gp.AddArc(new Rectangle(new Point(this.Width - this.Height, 0), new Size(this.Height, this.Height)), -90, 180);
                gp.CloseFigure();

                e.Graphics.FillPath(brush, gp);
            }

            base.OnPaint(e);
        }

If you really need to change the region I guess you would have to use a slightly bigger region then the one used for the drawing:

protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
        e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
        e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

        LinearGradientBrush brush = new LinearGradientBrush(this.ClientRectangle, Color.Aqua, Color.Blue, 90);

        using (GraphicsPath gp = new GraphicsPath())
        {
            AddRoundedRectangle(gp, new Point(1, 1), new Size(this.Size.Width - 2, Size.Height - 2));
            e.Graphics.FillPath(brush, gp);
        }

        using (GraphicsPath gp = new GraphicsPath())
        {
            AddRoundedRectangle(gp, new Point(0, 0), this.Size);
            this.Region = new Region(gp);
        }

        base.OnPaint(e);
    }

    private void AddRoundedRectangle(GraphicsPath gp, Point upperLeft, Size size)
    {
        gp.AddArc(new Rectangle(upperLeft, new Size(size.Height, size.Height)), 90, 180);
        gp.AddLine(new Point(size.Height / 2 , upperLeft.Y), new Point(size.Width - (size.Height / 2), upperLeft.Y));
        gp.AddArc(new Rectangle(new Point(size.Width - size.Height, upperLeft.Y), new Size(size.Height, size.Height)), -90, 180);
        gp.CloseFigure();
    }

The second option has the advantage of affecting events like MouseHover but may run into problems of you seeing the region's "border".


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...