4

2 labels in windows form

Both labels have AutoSize true & TextAlign MiddleCenter.

How can also label2 show smooth borders?

Here is the test code for handlers Form.Load(...) & Form.Paint(...):

int _cornerRadius = 10;
Point _locationLabel2;

// Form.Load(...)
private void Form3_Load(object sender, EventArgs e)
{
    // Step 1: Cut the label regions (seems to be ok, result is the same for both labels)
    GraphicsPath graphicsPath = _getRoundPath(label1.ClientRectangle, _cornerRadius);
    label1.Region = new Region(graphicsPath);
    graphicsPath = _getRoundPath(label2.ClientRectangle, _cornerRadius);
    label2.Region = new Region(graphicsPath);

    _locationLabel2 = this.PointToClient(label2.Parent.PointToScreen(label2.Location));
}

// Form.Paint(...)
private void Form3_Paint(object sender, PaintEventArgs e)
{
    using (Pen pen = new Pen(label1.BackColor, 3.0f))
    {
        // Step 2: Smooth the label borders (ok only for label1)
        _drawRoundedRectangle(e.Graphics, pen, label1.Location.X, label1.Location.Y, 
                              label1.ClientRectangle.Width, label1.ClientRectangle.Height, _cornerRadius);
        _drawRoundedRectangle(e.Graphics, pen, _locationLabel2.X, _locationLabel2.Y,
                              label2.ClientRectangle.Width, label2.ClientRectangle.Height, _cornerRadius);
    }
}

// Helper 1/3
private static GraphicsPath _getRoundPath(Rectangle rectangle, int radius)
{
    int x = rectangle.X;
    int y = rectangle.Y;
    int width = rectangle.Width;
    int height = rectangle.Height;

    radius = radius << 1;

    GraphicsPath path = new GraphicsPath();

    if (radius > 0)
    {
        if (radius > height) radius = height;
        if (radius > width) radius = width;
        path.AddArc(x, y, radius, radius, 180, 90);
        path.AddArc(x + width - radius, y, radius, radius, 270, 90);
        path.AddArc(x + width - radius, y + height - radius, radius, radius, 0, 90);
        path.AddArc(x, y + height - radius, radius, radius, 90, 90);
        path.CloseFigure();
    }
    else
    {
        path.AddRectangle(rectangle);
    }

    return path;
}

// Helper 2/3
private void _drawRoundedRectangle(Graphics graphics, Pen pen, int x, int y, int width, int height, int radius)
{
    RectangleF rectangle = new RectangleF(x, y, width, height);
    GraphicsPath path = _generateRoundedRectangle(graphics, rectangle, radius);
    SmoothingMode old = graphics.SmoothingMode;
    graphics.SmoothingMode = SmoothingMode.AntiAlias;
    graphics.DrawPath(pen, path);
    graphics.SmoothingMode = old;
}

// Helper 3/3
private static GraphicsPath _generateRoundedRectangle(Graphics graphics, RectangleF rectangle, int radius)
{
    GraphicsPath path = new GraphicsPath();
    float diameter = radius * 2.0F;
    SizeF sizeF = new SizeF(diameter, diameter);
    RectangleF arc = new RectangleF(rectangle.Location, sizeF);

    path.AddArc(arc, 180, 90); 
    arc.X = rectangle.Right - diameter;
    path.AddArc(arc, 270, 90);
    arc.Y = rectangle.Bottom - diameter;
    path.AddArc(arc, 0, 90);
    arc.X = rectangle.Left;
    path.AddArc(arc, 90, 90); 
    path.CloseFigure();

    return path;
}

Main code parts are from Arun Reginald Zaheeruddin

Pollitzer
  • 1,580
  • 3
  • 18
  • 28
  • __Not possible__, really. `Regions` do not allow anti-aliasing, hence the SmoothingMode will not allow any anti-aliased pixels.. Depending on your layout you may be able to owner-draw them, though as you do in label1.. – TaW Mar 06 '17 at 13:51
  • Try using `path.AddBezier` rather than `AddArc`. – helrich Mar 06 '17 at 14:34
  • duplicate? http://stackoverflow.com/questions/11347576/how-to-make-a-circle-shape-label-in-window-form – Ricky Divjakovski Mar 06 '17 at 14:55
  • @helrich: There is no difference between them at all. – TaW Mar 06 '17 at 14:56
  • @Ricky: Not a duplicate: The accepted answer there is all wrong and the others are doing what he already has. This is not about rounded corners but about smoothness. No smoothness for Regions. Period. – TaW Mar 06 '17 at 14:57
  • 1
    Do you really need changing region? You can draw your round label that supports `Transparent` back color with smooth round corners simply like [this example](http://stackoverflow.com/a/39230299/3110834). – Reza Aghaei Mar 06 '17 at 15:14
  • As mentioned by Taw, regions are not smooth, so you can not achieve smooth round edge using regions, if for any reason the way which built-in transparent background works in windows forms is not what you are looking for, you can cheat transparent layers using [this example](http://stackoverflow.com/a/36102074/3110834). – Reza Aghaei Mar 06 '17 at 15:17
  • 1
    Don't use a control. Just draw what you want. – LarsTech Mar 07 '17 at 15:24
  • @LarsTech: Sounds smart, will pick it up when my next drawing problem appears. – Pollitzer Mar 07 '17 at 16:08

1 Answers1

7

Solved it according to this answer by @Reza Aghaei.

Solution

using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
public class RoundLabel : Label
{
    [Browsable(true)]
    public Color _BackColor { get; set; }

    public RoundLabel()
    {
        this.DoubleBuffered = true;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        using (var graphicsPath = _getRoundRectangle(this.ClientRectangle))
        {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            using (var brush = new SolidBrush(_BackColor))
                e.Graphics.FillPath(brush, graphicsPath);
            using (var pen = new Pen(_BackColor, 1.0f))
                e.Graphics.DrawPath(pen, graphicsPath);
            TextRenderer.DrawText(e.Graphics, Text, this.Font, this.ClientRectangle, this.ForeColor);
        }
    }

    private GraphicsPath _getRoundRectangle(Rectangle rectangle)
    {
        int cornerRadius = 15; // change this value according to your needs
        int diminisher = 1;
        GraphicsPath path = new GraphicsPath();
        path.AddArc(rectangle.X, rectangle.Y, cornerRadius, cornerRadius, 180, 90);
        path.AddArc(rectangle.X + rectangle.Width - cornerRadius - diminisher, rectangle.Y, cornerRadius, cornerRadius, 270, 90);
        path.AddArc(rectangle.X + rectangle.Width - cornerRadius - diminisher, rectangle.Y + rectangle.Height - cornerRadius - diminisher, cornerRadius, cornerRadius, 0, 90);
        path.AddArc(rectangle.X, rectangle.Y + rectangle.Height - cornerRadius - diminisher, cornerRadius, cornerRadius, 90, 90);
        path.CloseAllFigures();
        return path;
    }
}
Community
  • 1
  • 1
Pollitzer
  • 1,580
  • 3
  • 18
  • 28
  • It worked the first time but after that I'm getting a normal label although I'm trying to create a round one. VS2013. – n.jmurov Jul 29 '17 at 11:05
  • @n.jmurov: Is your problem still there? – Pollitzer Jul 31 '17 at 06:59
  • Yes. I might try and attach a screenshot later. In the code they're RoundLabels but on the screen they're normal. I don't believe there's an error in code since it worked the first time. – n.jmurov Aug 01 '17 at 10:27
  • Nice solution: it looks quite "natural" on WinForms – Fabien Teulieres Oct 06 '20 at 19:47
  • @n.jmurov: I've uploaded a little sample project (VS 2010, .net 4.0), hope it helps ==> https://drive.google.com/file/d/0B8sOSdWzK9AZTEpxbjc1YldZNWM/view?usp=sharing&resourcekey=0-FkA-zb46cd-Mx3PkH_uTqw – Pollitzer Nov 29 '21 at 07:24