Introduction[INDENT]
Since this is my first thread in VB.NET forum(most of the time, I was in C/C++ forum), I want to share something that you might find it useful with your school project or with your works.

Button is already a MUST-HAVE element in every program (I couldn't imagine program without a single button would function). Because it is everywhere, its appearance affects your form's appearance greatly. Some people might not care about how their software looks, but to me, it is a very important aspect for my software.

NOTE: I am pretty new to VB.NET myself. If there is any mistake, please correct me.
[/INDENT]

Step 1: Creating UserControl and Essential Properties[INDENT]Creating UserControl into your project. Then imports the following:

Imports System.ComponentModel
Imports System.Windows.Forms
There are four important properties that you need.BackColor ForeColor Text BorderColor Because UserControl already has BackColor and ForeColor properties, you only need to construct Text and BorderColor properties Private _BorderColor As Color '' Button Border Color Public Property BorderColor() As Color Get Return _BorderColor End Get Set(ByVal value As Color) _BorderColor = value '' Force your control to re-draw itself '' in order to update the new border color Me.Invalidate() End Set End Property <EditorBrowsable(EditorBrowsableState.Always)> _ <Browsable(True)> _ Public Overrides Property Text() As String Get Return MyBase.Text End Get Set(ByVal value As String) MyBase.Text = value '' Force your control to re-draw itself '' in order to update the new inputted text Me.Invalidate() End Set End Property

[/INDENT]
Step 2: Drawing the Appearance[INDENT]
All the computer controls are just a graphical representation. It draws itself whenever it is necessary. Event Paint() occurs when control is needed to re-paint itself. Firstly, you need to draw the background and its border.

Private Sub CustomButton_Paint(ByVal sender As Object, _
                ByVal e As System.Windows.Forms.PaintEventArgs) _
                Handles Me.Paint

        '' Drawing background
        e.Graphics.Clear(Me.BackColor)

        '' Drawing border
        e.Graphics.DrawRectangle(New Pen(_BorderColor, 1), _
                                 0, 0, Me.Width - 1, Me.Height - 1)
    End Sub


[/INDENT]Step 3: Drawing the Text[INDENT]
Code above is only draw background and borderline. You need to draw text to the button as well.

Private Sub CustomButton_Paint(ByVal sender As Object, _
                ByVal e As System.Windows.Forms.PaintEventArgs) _
                Handles Me.Paint

        '' Drawing background
        e.Graphics.Clear(Me.BackColor)

        '' Drawing border
        e.Graphics.DrawRectangle(New Pen(_BorderColor, 1), _
                                 0, 0, Me.Width - 1, Me.Height - 1)

        TextRenderer.DrawText(e.Graphics, MyBase.Text, Me.Font, _
                              New Point(5, 5), Me.ForeColor)
    End Sub


It seems that your text is on the left side. You might want to be center. You can measure the width and the height of the text. Then calculate the correct X and Y coordinate to place your text to make it appear in the center of the button.

Private Sub CustomButton_Paint(ByVal sender As Object, _
                ByVal e As System.Windows.Forms.PaintEventArgs) _
                Handles Me.Paint

        '' Drawing background
        e.Graphics.Clear(Me.BackColor)

        '' Drawing border
        e.Graphics.DrawRectangle(New Pen(_BorderColor, 1), _
                                 0, 0, Me.Width - 1, Me.Height - 1)

        Dim measuredText As Size = TextRenderer.MeasureText(MyBase.Text, Me.Font)
        TextRenderer.DrawText(e.Graphics, MyBase.Text, Me.Font, _
                            New Point((Me.Width - measuredText.Width) / 2, _
                                      (Me.Height - measuredText.Height) / 2), Me.ForeColor)
    End Sub

[/INDENT]Step 4: Drawing the Blend Line[INDENT]
It seems that your button does not look cool enough. It is too simple. Perhaps, you can put a few lines near the upper border. The color of each line is the combination of background color and border color.
First Line Color = (BackgroundColor + BorderColor) / 1.5
Second Line Color = (BackgroundColor + FirstLineColor) / 1.5
'' Drawing background
e.Graphics.Clear(Me.BackColor)

'' Drawing border
e.Graphics.DrawRectangle(New Pen(_BorderColor, 1), _
0, 0, Me.Width - 1, Me.Height - 1)

Dim measuredText As Size = TextRenderer.MeasureText(MyBase.Text, Me.Font)
TextRenderer.DrawText(e.Graphics, MyBase.Text, Me.Font, _
New Point((Me.Width - measuredText.Width) / 2, _
(Me.Height - measuredText.Height) / 2), Me.ForeColor)

'' Drawing first line
Dim blendRed As Integer = (CInt(Me.BackColor.R) + _BorderColor.R) \ 1.5
Dim blendGreen As Integer = (CInt(Me.BackColor.G) + _BorderColor.G) \ 1.5
Dim blendBlue As Integer = (CInt(Me.BackColor.B) + _BorderColor.B) \ 1.5
Dim blendPen As New Pen(Color.FromArgb(255, If(blendRed > 255, 255, blendRed), _
If(blendGreen > 255, 255, blendGreen), _
If(blendBlue > 255, 255, blendBlue)), 1)
e.Graphics.DrawLine(blendPen, 1, 1, Me.Width - 2, 1)

'' Drawing second line
blendRed = (CInt(Me.BackColor.R) + blendPen.Color.R) \ 1.5
blendGreen = (CInt(Me.BackColor.G) + blendPen.Color.G) \ 1.5
blendBlue = (CInt(Me.BackColor.B) + blendPen.Color.B) \ 1.5
Dim blendPen2 As New Pen(Color.FromArgb(255, If(blendRed > 255, 255, blendRed), _
If(blendGreen > 255, 255, blendGreen), _
If(blendBlue > 255, 255, blendBlue)), 1)
e.Graphics.DrawLine(blendPen2, 1, 2, Me.Width - 2, 2)

[/INDENT]

Comments
Welcome! Informative tutorial.
Attachments 4.gif 1.23 KB Untitled-1.gif 0.36 KB Untitled-2.gif 0.49 KB Untitled-3.gif 0.49 KB

@invisal

I appreciate your effort but I'd like to add my comments on this post. First of all you need to overrides DefaultSize property - DefaultSize represents the size of the control when it is initially created/rendered.

Protected Overrides ReadOnly Property DefaultSize() As System.Drawing.Size
      Get
        Return MyBase.PreferredSize
        '
        ' OR you may choose your own size
        '
        'Return new size(150,30) 'Pixels
        ' OR use MinimumSize property
        '
        'Return MyBase.MinimumSize
      End Get
 End Property

Second and most important thing is you must have to apply DesignerSerializationVisibilityAttribute attribute to persist property value of a component in design mode. Note that as soon as you close the designer value of Text property will be discarded.

<EditorBrowsable(EditorBrowsableState.Always)> _
    <Browsable(True)> _
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
     Public Overrides Property Text() As String
        Get
            Return MyBase.Text
        End Get
        Set(ByVal value As String)
            MyBase.Text = value

            '' Force your control to re-draw itself
            '' in order to update the new inputted text
            Me.Invalidate()
        End Set
    End Property
This article has been dead for over six months. Start a new discussion instead.