Закругленная кнопка windows forms

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
class RoundedButton : Button
{
   GraphicsPath GetRoundPath(RectangleF Rect, int radius)
   {
      float r2 = radius / 2f;
      GraphicsPath GraphPath = new GraphicsPath();
      GraphPath.AddArc(Rect.X, Rect.Y, radius, radius, 180, 90);
      GraphPath.AddLine(Rect.X + r2, Rect.Y, Rect.Width - r2, Rect.Y);
      GraphPath.AddArc(Rect.X + Rect.Width - radius, Rect.Y, radius, radius, 270, 90);
      GraphPath.AddLine(Rect.Width, Rect.Y + r2, Rect.Width, Rect.Height - r2);
      GraphPath.AddArc(Rect.X + Rect.Width - radius, 
                       Rect.Y + Rect.Height - radius, radius, radius, 0, 90);
      GraphPath.AddLine(Rect.Width - r2, Rect.Height, Rect.X + r2, Rect.Height);
      GraphPath.AddArc(Rect.X, Rect.Y + Rect.Height - radius, radius, radius, 90, 90);
      GraphPath.AddLine(Rect.X, Rect.Height - r2, Rect.X, Rect.Y + r2);
      GraphPath.CloseFigure();
      return GraphPath;
   }
 
   protected override void OnPaint(PaintEventArgs e)
   {
      base.OnPaint(e);
      RectangleF Rect = new RectangleF(0, 0, this.Width, this.Height);
      using (GraphicsPath GraphPath = GetRoundPath(Rect, 50))
      {
        this.Region = new Region(GraphPath);
        using (Pen pen = new Pen(Color.CadetBlue, 1.75f))
        {
            pen.Alignment = PenAlignment.Inset;
            e.Graphics.DrawPath(pen, GraphPath);
        }
      }
   }
}

A lot of you requested to create a Round Button Control in WinForms. This plea came right after I published the article on how to create round corner controls using C# in WinForms. Naturally, this article will be continuation of the work done so far.

How to create Round Button Control in WinForms C# – Source Code

Rounded Corner Button

We already mention the issue of WinForms and how difficult sometimes is to visually style controls. One such example would be rounding the edges of a button. It is not uncommon these days to want that visual appeal of your application. So, today we will learn how to create our own round button control.

What we are going to build

Round Button Control in WinForms C#

As you can see, we are going to build an application, which uses a button with rounded edges. The button is visually appealing and functional. On click, we will display the message “Hi !!!”. However, the goal is not to create some useful app, but rather show you how to create a round button control in WinForms and C#.

Before we start the tutorial, please note that there are multiple solutions to this problem. One way to add rounded corners to a button is to inherit from the Control class. This is something that you may have not done before, but it is worth looking into it.

If you browse through .NET documentation you will soon realize that inheriting from Control may be the best solution for this situation. This is because the control implements the vary basic functionality required by classes that display information to the user. It defines the bounds of a control (its position and size), although it does not implement painting. It provides a window handle.

The change we want to make is visual. So, it makes sense to override the Paint method. However, creating a custom control using this class will be part of another tutorial. I am keeping this solution for a more complex scenario.

Today, we will create a button control with rounded edges in a simpler manner. By reusing our previous solution.

How to create Round Corner Controls in WinForms C# tutorial shows you how to paint on a UserControl. So, if we have a user control with rounded edges, what stops us from embedding a button inside? Well, nothing really. All we need to do is blend the button inside the control. The button will be rectangular, but we can blend it to the background of the control, so it won’t show.

Alternative solution

This is a quick and dirty way of doing this, but it is also simple and quite useful for most of the projects out there. Do remember, that there will be scenarios where this solution does not fit the requirements. In such scenario investigate how you can make use of the Control class and the Paint method. This stackoverflow answer might help you a lot. However, a special dedicated tutorial will follow.

How to create Round Button Control

Before we start this tutorial, make sure you have read and implemented the tutorial from our previous post. Because, you will need the source code. Your starting solution should look something like this:

Starting Project: Round Button Control

The only important files here are: RoundControl and GraphicsExtensions.cs. The RoundControl represents an empty user control with rounded edges. GraphicsExtensions class contains extension methods for the Graphics object that allow us to draw rectangle with round corners.

Next, add a new User Control. Name it RoundButton.

Add new User Control
Name the control: RoundButton

Navigate inside the code of the control and make sure to inherit from the RoundControl instead of UserControl. Then, build the solution. Your code should look like this:

public partial class RoundButton : RoundControl
{
     public RoundButton()
     {
          InitializeComponent();
     }
}

Just by inheriting from the RoundControl we already have the functionality we want – rounded corners. Please note that we also inherit the following properties: BackgroundColor, BorderColor, BorderWidth and Radius. Having these properties out of the box, makes our coding a lot simpler.

The Button

Right now, it is obvious that this control is not a button, and it doesn’t have the functionality of a button. However, we can easily upgrade this C# codebase and make it start acting as a button.

By default, a UserControl object can act as a control container only when you create the control. To make a UserControl host a constituent control after you put the UserControl on a Windows Form, you must change the default designer of the UserControl.

Add Button to RoundButton Control

As you can see from the image above, you will need to open the designer of the RoundButton control. Once opened, you can drag and drop a button from the Toolbox inside the RoundButton control. This actually is our real button. When placed inside the container it will not look like the image above. That is ok. You need to update some of the button properties via the designer in order to achieve the same look.

The important thing to conclude here is that we have built a custom user control with round corners. Inside we can host all different types of controls. Right now, we are hosting a button. So, the button, or any other control for that manner, will need to be blended in with the background of the original control. As a result, the control will look like it has round edges.

This is really beneficial because imagine if we want to have a text box with round corners? What will you do?

Well, of course you can create a new User Control and inherit from the RoundControl and then blend the TextBox with the background. This way you can easily create a text box with round corners. I am preparing another tutorial for this as well. So, stay tuned.

Button Properties

Before moving on, let’s update some of the button properties:

Anchor: Top, Bottom, Left, Right
AutoSizeMode: GrowAndShrink
FlatStyle: Flat
FlatAppearance.BorderSize: 0

If you set the button properties like I showed you, then you should have a very similar result like the image above.

Now we are ready to code in the behavior in C#.

Coding the behavior of the Round Button Control in C#

Because we already have the visual style we want, it is time to implement the desired behavior in C# as well. Well, what do we need? First of all, this control doesn’t have the properties and behavior as a button. As a result, we need to add them.

public string ButtonText { get => button1.Text; set => button1.Text = value; }
public bool UseMouseOverBackColor { get; set; } = false;
public Color MouseOverBackColor { get; set; }
private Color backgroundColor;

As you can see from the C# code snippet, we have three public properties and one private.

  • ButtonText property will display the text associated with the control
  • UseMouseOverBackColor is pretty self explanatory. If this is set to true then on mouse over the button will change its background color
  • MoseOverBackColor is the color that the button will use as background if the UseMouseOverBackColor property is set to true

The private field backgroundColor is a temporary variable that holds the background color of the button.

private void RoundButton_Load(object sender, EventArgs e)
{
    button1.FlatAppearance.MouseOverBackColor = Color.Transparent;
    button1.FlatAppearance.MouseDownBackColor = Color.Transparent;
    button1.BackColor = BackgroundColor;
    backgroundColor = BackgroundColor;
}

This C# code snippet handles the RoundButton control Load event. We use this event to further more blend the button with the control background. Sine, we are using flat appearance we need to set some of its properties like: MouseOverBackColor and MouseDownBackColor.

So why do we set these properties here and not in the designer? Well, as it turns out if you try to set the MouseOverBackColor and MouseDownBackColor to Transparent the designer will throw an error. This is just a workaround solution.

Remember, we do this so that we can blend the button into the control background. If the button has no border and no behaviour but the same background color then it will blend seamlessly into the control background.

Override Paint method

Next, we need to override the paint method like this:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    button1.Location = new Point(20, 20);
    button1.Size = new Size(Size.Width - 40, Size.Height - 40);
    button1.BackColor = BackgroundColor;
}

First, we start by calling base.OnPain(e). This will allow the RoundControl to draw the rounded corners of the RoundButton control. Then, as you can see we set the location and the size of the button. I decided to put this code here since I want the changes to always be reflected whenever the button is redrawn. Please note that this code is also used by the designer as well. That is the reason why button1.BackColor = BackgroundColor is placed in the OnPaint event. As a result, If the background color is changed during Design Time, the changes will be reflected immediately.

The “Magic Numbers”

If you are not familiar with the expression: magic numbers. Then please read about it here. I do not condone using code like this and it should be avoided. However, this is a tutorial on how to create Round Button Control and not how to write clean code. This is the only reason why I left the code as it is shown in the C# code snippet.

To sum it up: A magic number in C# is a unique value with unexplained meaning. This definition should scare you off from writing code like this. At the very least replace this value with a properly named constant.

So, how did I get to these values? Well, based on a couple of test I did, it turned out that the best location for the button should be X = 20 and Y = 20. Why not place the button at position (0,0)? Because the button rectangle itself will overlap with the rounded corners of the control.

Same logic goes for the Width and Height. You just have to take into consideration that the button starts at position (20,20) and you reserve 20 additional pixels spacing for the control to draw the rounded edges on the bottom and the right side.

Round Button Click Event

Since I did not want to add new Click event I am using the one already hooked to the UserControl itself. This leads me to handle the Button_Click like so:

private void button1_Click(object sender, EventArgs e) => InvokeOnClick(this, e);

This C# code allows me to raise Click event when the control is clicked or the button is clicked. I am doing this because of the space left between the RoundControl and the Button. If the user clicks at position (0,0) of the control, it will raise the Click event of the control. But if the user clicks on the button the event is handled so that the Click event of the control is raised as well.

private void button1_MouseEnter(object sender, EventArgs e)
{
    if (UseMouseOverBackColor)
        BackgroundColor = button1.BackColor = MouseOverBackColor;
}
private void button1_MouseLeave(object sender, EventArgs e)
{
    if (UseMouseOverBackColor)
        BackgroundColor = button1.BackColor = backgroundColor;
}
private void RoundButton_MouseEnter(object sender, EventArgs e) => button1_MouseEnter((object)sender, e);
private void RoundButton_MouseLeave(object sender, EventArgs e) => button1_MouseLeave((object)sender, e);

Round Button Mouse Events

Since I did not want to create a plain button, I added some effects on MouseEnter and MouseLeave events. The C# code snippet is pretty obvious. We are changing the background of the round button when the mouse pointer enters the button and then leaves it as well. The only thing noteworthy here to explain is that we do this for both controls: the RoundButton and Button itself. This is because they are separate controls. Meaning that once you enter in one control, you leave the other. So, they have to be synced.

Conclusion

There are many ways C# and .NET allows us to implement round corner design. I think this solution is very simple and easy to follow. It will be at a satisfactory level in many projects that require improving the visual style of the classic controls. However, in times when we need something quite custom, then you have to look elsewhere for a solution. To be more specific, you will need to inherit from Control class. We will create a brand new tutorial explaining how to handle that type of situation. But, before doing that, we can quickly create round cornered text box using the same principles we explained here.

  • 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.

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.

//the modified button class looks like this

 class ButtonModified : System.Windows.Forms.Button
    {
        //we can use this to modify the color of the border 
        public Color BorderColor = Color.LightGray;
        //we can use this to modify the border size
        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)
        {
            // to draw the control using base OnPaint
            base.OnPaint(pevent);
            //to modify the corner radius
            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.

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:

 //Auto Generated Designer When We Drag and Drop Button 
  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();
  
            // 
            // Btn_next
            // 
            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;
            // 
            // Buttontype
            // 
            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.

Да-да, я знаю, что лучше не делать на 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 — то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

Skip to content

With windows form application, there are multiple ways to create a custom shaped button. One of the option is to use a picture box and set a round image as background. The other option which is the best one is to create a custom button by inheriting from the Button class and overriding the OnPaint event. With this approach, we will get all the features of a windows button with a custom shape. Steps to create a rounded button is explained below,

  1. Add a new Class named RoundButton

Add a new Class to your project

2. Inherit the Button class and override the OnPaint method as follows

public class RoundButton : Button
{
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
var graphicsPath = new GraphicsPath();
graphicsPath.AddEllipse(0, 0, ClientSize.Width, ClientSize.Height);
this.Region = new Region(graphicsPath);
base.OnPaint(e);
}
}

3. Build the project and open the Form where button is to be placed. The new RoundButton would appear in the ToolBox in the Components section at the top of the tool list

4. Drag and Drop the button to the form

5. Modify the width and the height of the button to change the shape from ellipse to circle.

I changed the FlatStyle to Popup, BackColor to ActiveCaption and Width and Height to 75 which draws a rounded button on the form.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Не устанавливается песочница windows 10
  • Свойства видеоадаптера для дисплея windows 10
  • Ошибка netbt 4321 windows
  • Джеффри рихтер создание эффективных win32 приложений с учетом специфики 64 разрядной версии windows
  • Как достать файл из буфера обмена в windows 10