C# - Custom Button Control

Creating custom controls with the .Net Framework is relatively easy. In this article I explain how to create a custom button control using GDI.

Most controls can be extended by creating a class that inherits from the control and the System.Windows.Forms.Button is one of them. To create a custom button control you can simply inherit from the Button control and override or add new functionality. For this tutorial, I'll explain how to use GDI to design a custom button.

First you'll need to create a new class that inherits from System.Windows.Forms.Button. You then need to override the OnPaint method. Overriding this method will allow you to repaint over the button. Your code should look similar to listing 1.1 below.
Listing 1.1
  1. using System;  
  2. using System.Drawing;  
  3. using System.Drawing.Drawing2D;  
  4. using System.Collections.Generic;  
  5. using System.Linq;  
  6. using System.Text;  
  7. using System.Windows.Forms;  
  8.  
  9. class xButton : Button  
  10. {  
  11.     protected override void OnPaint(PaintEventArgs pevent)  
  12.     {  
  13.     }  
  14. } 
The OnPaint method accepts a PaintEventArgs argument, which exposes the Graphics object that is used to paint the control. Using this Grapjics object, you can repaint the control as seen in listing 1.2 below.
Listing 1.2
  1. protected override void OnPaint(PaintEventArgs pevent)  
  2. {  
  3.     Graphics g = pevent.Graphics;  
  4.  
  5.     /** Area of Button */  
  6.     Rectangle area = new Rectangle(0, 0, this.Width, this.Height);  
  7.  
  8.     /** Fill the area with a Blue solid color */  
  9.     g.FillRectangle(new SolidBrush(Color.Blue), area);  
  10. } 
The Graphics object exposes several methods for painting, one of which is the FillRectangle() method. This method takes the area to paint and the color to paint the area. In the above code a Rectangle instance specifies the area to paint, which is the full area of the button. If you run the code, you will notice, that the button caption does not appear. This is because you must draw the button text onto the button. This can be done using the Graphics objects DrawString() method as shown in listing 1.3 below.
Listing 1.3
  1. int x = 0;  
  2. int y = 0;  
  3. g.DrawString(this.Text, new Font(this.Font, this.Font.Style)new SolidBrush(this.ForeColor), x, y)
When using the DrawString() method, you must specify where on the button you want to draw the button text as seen by the x and y variables. To position the text in the center of the button, you must first get the size of the text. This can be done using the MeasureString() method of the Graphics object. Once you have the text size, its easy to calculate the center text position. The code in listing 1.4 below shows how to align the text in the center of the button.
Listing 1.4
  1. SizeF textSize = g.MeasureString(this.Text, this.Font);  
  2. int x = (int)(area.Width - textSize.Width) / 2;  
  3. int y = (int)(area.Height - textSize.Height) / 2; 
You can add a hover event to the button so that the background color changes when the mouse moves over the button. To achieve this, you need to override the OnMouseEnter and the OnMouseLeave methods and store the mouse action in a variable. Listing 1.5 below shows a complete button class with mouse hover and click events.
Listing 1.5
  1. using System;  
  2. using System.Drawing;  
  3. using System.Drawing.Drawing2D;  
  4. using System.Collections.Generic;  
  5. using System.Linq;  
  6. using System.Text;  
  7. using System.Windows.Forms;  
  8.  
  9. class xButton : Button  
  10. {  
  11.     bool _hoverState = false;  
  12.     bool _downState = false;  
  13.  
  14.     public xButton()  
  15.     {  
  16.         this.BackColor = Color.Black;  
  17.         this.HoverBackgroundColor = Color.Black;  
  18.         this.ClickedBackgroundColor = Color.White;  
  19.         this.BackgroundGradientOffset = 0;  
  20.     }  
  21.  
  22.     public Point TextPosition  
  23.     {  
  24.         set;  
  25.         get;  
  26.     }  
  27.  
  28.     public Color ClickedBackgroundColor  
  29.     {  
  30.         set;  
  31.         get;  
  32.     }  
  33.  
  34.     public Color HoverBackgroundColor  
  35.     {  
  36.         set;  
  37.         get;  
  38.     }  
  39.  
  40.     public int BackgroundGradientOffset  
  41.     {  
  42.         set;  
  43.         get;  
  44.     }  
  45.  
  46.     protected override void OnPaint(PaintEventArgs pevent)  
  47.     {  
  48.         Graphics g = pevent.Graphics;  
  49.    
  50.         Rectangle area = new Rectangle(0, 0, this.Width, this.Height);  
  51.  
  52.         g.DrawRectangle(new Pen(new SolidBrush(this.BackColor)), area);  
  53.  
  54.         if (this._hoverState)  
  55.         {  
  56.             g.FillRectangle(new SolidBrush(ClickedBackgroundColor), area);  
  57.             g.DrawString(this.Text, new Font(this.Font, this.Font.Style)new SolidBrush(this.BackColor)this.TextPosition.X, this.TextPosition.Y);  
  58.         }  
  59.         else if (this._downState)  
  60.         {  
  61.             g.FillRectangle(new SolidBrush(Color.Black), area);  
  62.             g.DrawString(this.Text, new Font(this.Font, this.Font.Style)new SolidBrush(this.BackColor)this.TextPosition.X, this.TextPosition.Y);  
  63.         }  
  64.         else  
  65.         {  
  66.             int red = (this.BackColor.R > this.BackgroundGradientOffset) ? this.BackColor.R - this.BackgroundGradientOffset : 0;  
  67.             int green = (this.BackColor.G > this.BackgroundGradientOffset) ? this.BackColor.G - this.BackgroundGradientOffset : 0;  
  68.             int blue = (this.BackColor.B > this.BackgroundGradientOffset) ? this.BackColor.B - this.BackgroundGradientOffset : 0;  
  69.             Color gradientColor = Color.FromArgb(red, green, blue);  
  70.             LinearGradientBrush lgBrush = new LinearGradientBrush(area, this.BackColor, gradientColor, 1);  
  71.             gradientColor = Color.FromArgb(red, green, blue);  
  72.               
  73.             g.FillRectangle(lgBrush, area);  
  74.             g.DrawString(this.Text, new Font(this.Font, this.Font.Style)new SolidBrush(this.ForeColor)this.TextPosition.X, this.TextPosition.Y);  
  75.         }  
  76.     }  
  77.  
  78.     protected override void  OnMouseEnter(EventArgs e)  
  79.     {  
  80.         _hoverState = true;   
  81.         base.OnMouseEnter(e);  
  82.     }  
  83.  
  84.     protected override void OnMouseLeave(EventArgs e){  
  85.           
  86.         _hoverState = false;  
  87.         base.OnMouseLeave(e);  
  88.     }  
  89.  
  90.     protected override void OnMouseDown(MouseEventArgs e)  
  91.     {  
  92.         _downState = true;  
  93.         _hoverState = false;  
  94.         base.OnMouseDown(e);  
  95.     }  
  96.  
  97.     protected override void OnMouseUp(MouseEventArgs e)  
  98.     {  
  99.         _downState = false;  
  100.         _hoverState = false;   
  101.         base.OnMouseUp(e);  
  102.     }  
  103. } 

No comments:

Post a Comment