Как закруглить кнопку в windows forms

What about ‘GDI’?

Implementation Example:

 #region <Round Corners> : (Properties)
        // [Use Round Corners]
        private bool useRoundCorners = false;

        [Category("Control Corners"), DisplayName("Round Corners")]
        [Description("Set Round Corners.")]
        [Browsable(true)]
        public bool UseRoundBorders
        {
            get { return useRoundCorners; }
            set { if (useRoundCorners != value) { useRoundCorners = value; Invalidate(); } }
        }

        // [Ellipse Radius]
        private int ellipseRadius = 20;

        [Category("Control Corners"), DisplayName("Radius")]
        [Description("Set Corner (Ellipse) Radius")]
        [Browsable(true)]
        public int EllipseRadius
        {
            get { return ellipseRadius.FixedValue(0, 90); }
            set { if (ellipseRadius != value.FixedValue(0, 90)) { ellipseRadius = value; Invalidate(); } }
        }
        #endregion

        #region <Round Corners> : (Draw)
        [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
        private static extern IntPtr CreateRoundRectRgn
        (
            int nLeftRect,     // x-coordinate of upper-left corner
            int nTopRect,      // y-coordinate of upper-left corner
            int nRightRect,    // x-coordinate of lower-right corner-
            int nBottomRect,   // y-coordinate of lower-right corner
            int nWidthEllipse, // width of ellipse
            int nHeightEllipse // height of ellipse
        );


        /// <summary> Draw Corners (Round or Square). </summary>
        /// <param name="e"></param>
        private void DrawCorners()
        {
            if (useRoundCorners) { this.Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, ellipseRadius, ellipseRadius)); }
            else { this.Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, 0, 0)); }
        }
        #endregion

    /// <summary> Redraw (Update) the Control. </summary>
    /// <param name="e"></param>
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        DrawCorners();
    }    

Extension to Limit Round Corner Radius (*Range: 0-90)

Author: Salvador

// Extension to Set Min. & Max. Values to Properties
public static class Extensions
{
    public static int FixedValue(this int value, int min, int max)
    {
        if (value >= min && value <= max) { return value; }
        else if (value > max) { return max; }
        else if (value < min) { return min; }
        else { return 1; }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
    public class RoundButton : Control
    {
        public Color BackColor2 { get; set; }
        public Color ButtonBorderColor { get; set; }
        public int ButtonRoundRadius { get; set; }
 
        public Color ButtonHighlightColor { get; set; }
        public Color ButtonHighlightColor2 { get; set; }
        public Color ButtonHighlightForeColor { get; set; }
 
        public Color ButtonPressedColor { get; set; }
        public Color ButtonPressedColor2 { get; set; }
        public Color ButtonPressedForeColor { get; set; }
 
        private bool IsHighlighted;
        private bool IsPressed;
 
        public RoundButton()
        {
            Size = new Size(100, 40);
            ButtonRoundRadius = 30;
            BackColor = Color.Gainsboro;
            BackColor2 = Color.Silver;
            ButtonBorderColor = Color.Black;
            ButtonHighlightColor = Color.Orange;
            ButtonHighlightColor2 = Color.OrangeRed;
            ButtonHighlightForeColor = Color.Black;
 
            ButtonPressedColor = Color.Red;
            ButtonPressedColor2 = Color.Maroon;
            ButtonPressedForeColor = Color.White;
        }
 
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams createParams = base.CreateParams;
                createParams.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
                return createParams;
            }
        }
 
        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
 
            var foreColor = IsPressed ? ButtonPressedForeColor : IsHighlighted ? ButtonHighlightForeColor : ForeColor;
            var backColor = IsPressed ? ButtonPressedColor : IsHighlighted ? ButtonHighlightColor : BackColor;
            var backColor2 = IsPressed ? ButtonPressedColor2 : IsHighlighted ? ButtonHighlightColor2 : BackColor2;
 
 
            using (var pen = new Pen(ButtonBorderColor, 1))
                e.Graphics.DrawPath(pen, Path);
 
            using (var brush = new LinearGradientBrush(ClientRectangle, backColor, backColor2, LinearGradientMode.Vertical))
                e.Graphics.FillPath(brush, Path);
 
            using (var brush = new SolidBrush(foreColor))
            {
                var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
                var rect = ClientRectangle;
                rect.Inflate(-4, -4);
                e.Graphics.DrawString(Text, Font, brush, rect, sf);
            }
 
            base.OnPaint(e);
        }
 
        protected override void OnPaintBackground(PaintEventArgs e)
        {
        }
 
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            IsHighlighted = true;
            Parent.Invalidate(Bounds, false);
            Invalidate();
        }
 
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            IsHighlighted = false;
            IsPressed = false;
            Parent.Invalidate(Bounds, false);
            Invalidate();
        }
 
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            Parent.Invalidate(Bounds, false);
            Invalidate();
            IsPressed = true;
        }
 
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            Parent.Invalidate(Bounds, false);
            Invalidate();
            IsPressed = false;
        }
 
        protected GraphicsPath Path 
        {
            get
            {
                var rect = ClientRectangle;
                rect.Inflate(-1, -1);
                return GetRoundedRectangle(rect, ButtonRoundRadius);
            }
        }
 
        public static GraphicsPath GetRoundedRectangle(Rectangle rect, int d)
        {
            var gp = new GraphicsPath();
 
            gp.AddArc(rect.X, rect.Y, d, d, 180, 90);
            gp.AddArc(rect.X + rect.Width - d, rect.Y, d, d, 270, 90);
            gp.AddArc(rect.X + rect.Width - d, rect.Y + rect.Height - d, d, d, 0, 90);
            gp.AddArc(rect.X, rect.Y + rect.Height - d, d, d, 90, 90);
            gp.CloseFigure();
 
            return gp;
        }
    }
  • Remove From My Forums
  • Question

  • I have used many codes for generating Rounded Corner button. But, that are all have some issue in the edge or in the corner radius border.

    I want the clean code, which should be like perfect Rounded corner edge in the button (like our mobile phone edge with descent color).

    Can anybody share the sample source code with clean examples…?

    • Moved by

      Tuesday, May 5, 2020 1:28 PM
      Winforms related

Answers

  • It was just a test to create it dynamically and see that it is anti-aliased

    For a real control, you must add a Constructor without parameters

    Test, to be improved =>

    [Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(System.ComponentModel.Design.IDesigner))]
    public partial class RoundedUserControl : System.Windows.Forms.UserControl
    {
        private int nRadius = 20;
    
        // crash on VS 2015
    
        //[Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
        //[Description("Text for User Control"), Category("Data")]
        //public override string Text 
        //{
        //    get { return this.Text; }
        //    set { this.Text = value; }
        //}
    
        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
        [Description("Text for User Control"), Category("Data")]
        public string ControlText
        {
            get { return this.Text; }
            set { this.Text = value; }
        }
    
        public int Radius
        {
            get { return nRadius; }
            set { nRadius = value; }
        }
    
        private System.Drawing.Color borderColor = System.Drawing.Color.Red;
    
        public System.Drawing.Color BorderColor
        {
            get { return borderColor; }
            set { borderColor = value; }
        }
    
        private System.Drawing.Color fillColor = System.Drawing.SystemColors.ButtonFace;
    
        public System.Drawing.Color FillColor
        {
            get { return fillColor; }
            set { fillColor = value; }
        }
    
        private System.Drawing.Color oldFillColor;
    
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            oldFillColor = FillColor;
            FillColor = System.Drawing.SystemColors.ButtonHighlight;
            this.Invalidate();
        }
    
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            FillColor = oldFillColor;
            this.Invalidate();
        }
    
        private int nBorderSize = 4;
    
        public int BorderSize
        {
            get { return nBorderSize; }
            set { nBorderSize = value; }
        }
    
        public RoundedUserControl()
        {
            //InitializeComponent();
        }
    
        public RoundedUserControl(int nRadius = 20, System.Drawing.Color? fillColor = null, System.Drawing.Color? borderColor = null, int borderSize = 4) : this()
        {
            Radius = nRadius;
            FillColor = fillColor ?? System.Drawing.SystemColors.ButtonFace;
            BorderColor = borderColor ?? System.Drawing.Color.Red;
            BorderSize = borderSize;
        }
    
    
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
          
            nRadius = Math.Min(nRadius, Height - BorderSize * 2);
            Rectangle rect = new Rectangle(BorderSize, BorderSize, Width - BorderSize * 2, Height - BorderSize * 2);
            using (System.Drawing.Drawing2D.GraphicsPath gp = CreatePath(rect, nRadius, false))
            {
                System.Drawing.Pen pen = new System.Drawing.Pen(BorderColor, BorderSize);
                pen.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;
                e.Graphics.FillPath(new SolidBrush(FillColor), gp);
                e.Graphics.DrawPath(pen, gp);
            }
    
            //System.Drawing.Size textSize = TextRenderer.MeasureText(this.Text, this.Font);
            System.Drawing.Size textSize = TextRenderer.MeasureText(this.ControlText, this.Font);
            var nWidth = ((this.Width - textSize.Width) / 2);
            var nHeight = ((this.Height - textSize.Height) / 2);
            System.Drawing.Point drawPoint = new System.Drawing.Point(nWidth, nHeight);
            Rectangle normalRect = new Rectangle(drawPoint, textSize);
            TextRenderer.DrawText(e.Graphics, this.Text, this.Font, normalRect, ForeColor);
        }
    
        public static System.Drawing.Drawing2D.GraphicsPath CreatePath(Rectangle rect, int nRadius, bool bOutline)
        {
            int nShift = bOutline ? 1 : 0;
            System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
            path.AddArc(rect.X + nShift, rect.Y, nRadius, nRadius, 180f, 90f);
            path.AddArc((rect.Right - nRadius) - nShift, rect.Y, nRadius, nRadius, 270f, 90f);
            path.AddArc((rect.Right - nRadius) - nShift, (rect.Bottom - nRadius) - nShift, nRadius, nRadius, 0f, 90f);
            path.AddArc(rect.X + nShift, (rect.Bottom - nRadius) - nShift, nRadius, nRadius, 90f, 90f);
            path.CloseFigure();
            return path;
        }  
    }

    • Marked as answer by
      Gani tpt
      Tuesday, May 12, 2020 7:43 AM
    • Unmarked as answer by
      Gani tpt
      Tuesday, May 12, 2020 11:36 AM
    • Marked as answer by
      Gani tpt
      Wednesday, May 13, 2020 3:29 AM

  • You must call Invalidate() after you change the text (or
    Refresh())

    .Text should work but as I put in comments, it crashes on my configuration (VS 2015, Windows 10)…

    • Marked as answer by
      Gani tpt
      Wednesday, May 13, 2020 5:22 PM

  • Download demo (RAR) — 50.1 KB
  • Download demo (ZIP) — 52.4 KB

Introduction

This tip gives an overview to modify existing button control in Winforms to achieve rounded edge Button Control (or rounded corner button control).

Background

Recently, I came across a requirement which asked for rounded edge button (or rounded corner button). I know WinForms is almost outdated and this feature can be achieved very easily in WPF. This tip is written for any programmer who is struggling to get this requirement done.

Image 1

Final Output

Using the Code

The basic idea of getting this done is to inherit button control to a class ButtonModified and override OnPaint to obtain our requirement.

The first thing is to set the button’s FlatStyle as «Flat» from constructor. We can also set the common properties which we use throughout our project like Font, BorderSize, etc. This can also be modified individually from the forms which we refer this.


 class ButtonModified : System.Windows.Forms.Button
    {
        
        public Color BorderColor = Color.LightGray;
        
        public int BorderSize = 5;
        public ButtonModified()
        {
            FlatStyle = FlatStyle.Flat;
            BackColor = Color.White;
            FlatAppearance.BorderColor = BorderColor;
            FlatAppearance.BorderSize = BorderSize;
            Font = new System.Drawing.Font("VAGRounded-Light", 
            30F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel, ((byte)(0)));
            ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(84)))), 
            		((int)(((byte)(33)))), ((int)(((byte)(107)))));
            
            this.MouseDown += new MouseEventHandler(ButtonLastest_MouseDown);
            this.MouseUp += new MouseEventHandler(ButtonLastest_MouseUp);     
        }

        void ButtonLastest_MouseUp(object sender, MouseEventArgs e)
        {
            ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(84)))), 
            			((int)(((byte)(33)))), ((int)(((byte)(107)))));
            BackColor = Color.White;
        }

        void ButtonLastest_MouseDown(object sender, MouseEventArgs e)
        {
            BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(84)))), 
            			((int)(((byte)(33)))), ((int)(((byte)(107)))));
            ForeColor = System.Drawing.Color.White;
           
        }
         int top ; 
         int left;
         int right ;
         int bottom;        

        protected override void OnPaint(PaintEventArgs pevent)
        {
            
            base.OnPaint(pevent);
            
            int CornerRadius = 18;
            
            Pen DrawPen = new Pen(BorderColor);
            GraphicsPath gfxPath_mod = new GraphicsPath();

            top = 0;
            left = 0;
            right = Width;
            bottom = Height;
           
            gfxPath_mod.AddArc(left, top, CornerRadius, CornerRadius, 180, 90);
            gfxPath_mod.AddArc(right - CornerRadius, top, CornerRadius, CornerRadius, 270, 90);
            gfxPath_mod.AddArc(right - CornerRadius, bottom - CornerRadius, 
				CornerRadius, CornerRadius, 0, 90);
            gfxPath_mod.AddArc(left, bottom - CornerRadius, CornerRadius, CornerRadius, 90, 90);

            gfxPath_mod.CloseAllFigures();

            pevent.Graphics.DrawPath(DrawPen, gfxPath_mod);           

            int inside = 1;

            Pen newPen = new Pen(BorderColor, BorderSize);
            GraphicsPath gfxPath = new GraphicsPath();
            gfxPath.AddArc(left + inside + 1, top + inside, CornerRadius, CornerRadius, 180, 100);

            gfxPath.AddArc(right - CornerRadius - inside - 2, 
            	top + inside, CornerRadius, CornerRadius, 270, 90);
            gfxPath.AddArc(right - CornerRadius - inside - 2, 
            	bottom - CornerRadius - inside - 1, CornerRadius, CornerRadius, 0, 90);

            gfxPath.AddArc(left + inside + 1, 
            bottom - CornerRadius - inside, CornerRadius, CornerRadius, 95, 95);
            pevent.Graphics.DrawPath(newPen, gfxPath);

            this.Region = new System.Drawing.Region(gfxPath_mod);
        }
    }

Now we have two approaches.

Easier Approach

The easier way is to first build your solution and the button will be available in your toolbar which you can use like normal button control.

Image 2

Approach Two to Modify Existing Buttons Already Aligned and Placed In Project

We all know that normal buttons when placed in winform by dragging and dropping will generate a designer class. We can easily modify our designer class as explained below. To modify the existing buttons in our project:

 
  Partial Class Buttontype
    {      
        Private System.ComponentModel.IContainer Components = Null;
        
        Protected Override Void Dispose(bool Disposing)
        {
            if (Disposing && (Components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #Region Windows Form Designer Generated Code

        Private Void Initializecomponent()
        {
            this.btn_Next = new System.Windows.Forms.Button();

            this.SuspendLayout();
  
            
            
            
            this.btn_Next.BackColor = System.Drawing.Color.White;
            this.btn_Next.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
            this.btn_Next.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.btn_Next.Font = New System.Drawing.Font("Verdana", 20.25F, 
            System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((Byte)(0)));
            this.btn_Next.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(84)))), 
            		((Int)(((byte)(33)))), ((Int)(((byte)(107)))));
            this.btn_Next.Location = New System.Drawing.Point(244, 204);
            this.btn_Next.Name = "Btn_next";
            this.btn_Next.Size = New System.Drawing.Size(234, 94);
            this.btn_Next.TabIndex = 63;
            this.btn_Next.Text = "Next";
            this.btn_Next.UseCompatibleTextRendering = True;
            this.btn_Next.UseVisualStyleBackColor = False;
            
            
            
            this.AutoScaleDimensions = New System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = New System.Drawing.Size(778, 374);
            this.Controls.Add(this.btn_Next);

            this.Name = "Buttontype";
            this.Text = "Aint";
            this.ResumeLayout(false);
        }

        #Endregion

        Public System.Windows.Forms.Button Btn_next;
    }

See the bolded portion of the code:

this.btn_Next = new System.Windows.Forms.Button();

This needs to be replaced as:

this.btn_Next = new ButtonDemo.ButtonModified();

This will update your designer once you rebuild the solution.

The method is depicted here so as to modify any existing project easily without any hassles, i.e., you wouldn’t need to align your existing button or modify the font, etc. Use this only if your requirement is just to round off your existing Buttons which were previously aligned and set.

Points of Interest

This is just a method which I came up with. If someone comes up with a better solution, it can be posted here so that it can be a reference to anyone who needs this in the future.

This member has not yet provided a Biography. Assume it’s interesting and varied, and probably something to do with programming.

Да-да, я знаю, что лучше не делать на Windows Forms красивые приложения – для этого есть WPF. Однако, если проект уже разросся, то переносить его из-за пары красивостей не хочется. Тем более, что при достаточной сноровке можно делать симпатичные кнопочки и на Windows Forms.

Итак, сначала создаем кнопку. Называем её неоригинально – button1. Сначала закругляем ей края при загрзуке формы (событие лоад):

System.Drawing.Drawing2D.GraphicsPath Button_Path = new System.Drawing.Drawing2D.GraphicsPath();
            Button_Path.AddEllipse(-10, -9, this.button1.Width+20, 40);
            Region Button_Region = new Region(Button_Path);
            this.button1.Region = Button_Region;

Числа подбираются индивидуально — чтобы края у кнопки были закруглены равномерно — я же не заню, какого размера она у вас.

Теперь нам надо закрасить кнопку. Но не просто однотонно, а с градиентом. Это тоже реализуется довольно просто. В обработчик перерисовщика кнопки кидаем:

    private void button1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
        
                g.FillRectangle(
                    new LinearGradientBrush(PointF.Empty, new PointF(0, button1.Height), Color.Black, Color.Green),
                    new RectangleF(PointF.Empty, button1.Size));
            g.DrawString("Вход за преподавателя", new Font("Arial", 10), System.Drawing.Brushes.White, new Point(10, 3));

        }

И получается вот такая картина:

Не сказать, чтобы очень красиво, но своей цели мы все же добились. Если вам требуется помощь программиста по C# или другим языкам программирования, то вы можете написать мне — за небольшую плату я вам с удовольствием помогу.


Автор этого материала — я — Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML — то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, visual studio, windows forms

  • Как закриптовать вирус от windows defender
  • Как закрепить страницу на панели задач windows
  • Как закрепить ярлыки на рабочем столе windows 10 чтобы они не перемещались
  • Как закрепить ссылку на панели задач windows 10
  • Как закрепить расположение значков на рабочем столе windows 10