Creaintg VB.NET Buttons with Mettalic or Gradient Effect

I have the need to create VB.NET form buttons with a Gradient effect.  I have located some code to do this with the Form itself and that works perfectly, however when I try it with the Button within that form it does not work as expected.  The buttons either have the gradient with no Text  (the gradient disappears and the Text re-appears on Button Mouse Hover or Click) or no gradient at all.  The codes is as follows:

  Private Sub Button1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Button1.Paint
        'Create the Metallic gradient affect on Button1 ....
        '

        Dim g As Graphics = Button1.CreateGraphics

        Dim intWidth As Integer = Button1.Width - 3
        Dim intHeight As Integer = Button1.Height - 3

        Dim lgBrush As New LinearGradientBrush(New Point(1, 1), New Point(intWidth, intHeight), _
                           Color.White, Color.FromArgb(190, 190, 190))

        g.FillRectangle(lgBrush, 0, 0, intWidth, intHeight)

    End Sub

The same code as I said works perfectly with the forms itself but not the buttons and the results on the buttons vary depending on the Flatstyle setting.  Can anyone help with some advice on what is wrong OR provide some code that might do the job?
bertpetAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

planoczCommented:
here is a small button test app that might help you in your button colors.
Public Class frmColorButtons
    Inherits System.Windows.Forms.Form
    Dim bMouseInButton As Boolean
    Dim bHit As Boolean
    Dim RestoreBackColor As System.Drawing.Color
    Dim x As Color = Color.Red
    Dim x2 As Color = Color.Blue
    Private lastPressedLabel As LabelEx
#Region " Windows Form Designer generated code "
    Public Sub New()
        MyBase.New()
 
        'This call is required by the Windows Form Designer.
        InitializeComponent()
 
        'Add any initialization after the InitializeComponent() call
        bMouseInButton = True
    End Sub
    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub
    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
 
    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents Button2 As System.Windows.Forms.Button
    Friend WithEvents Label2 As Buttons.LabelEx
    Friend WithEvents Label3 As Buttons.LabelEx
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(frmColorButtons))
        Me.Label1 = New System.Windows.Forms.Label
        Me.Button1 = New System.Windows.Forms.Button
        Me.Button2 = New System.Windows.Forms.Button
        Me.Label2 = New Buttons.LabelEx
        Me.Label3 = New Buttons.LabelEx
        Me.SuspendLayout()
        '
        'Label1
        '
        Me.Label1.BackColor = System.Drawing.Color.Yellow
        Me.Label1.Image = CType(resources.GetObject("Label1.Image"), System.Drawing.Image)
        Me.Label1.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft
        Me.Label1.Location = New System.Drawing.Point(8, 52)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(96, 32)
        Me.Label1.TabIndex = 0
        Me.Label1.Text = "Label1"
        Me.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
        '
        'Button1
        '
        Me.Button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat
        Me.Button1.Location = New System.Drawing.Point(16, 12)
        Me.Button1.Name = "Button1"
        Me.Button1.TabIndex = 1
        Me.Button1.Text = "Button1"
        '
        'Button2
        '
        Me.Button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat
        Me.Button2.Location = New System.Drawing.Point(124, 12)
        Me.Button2.Name = "Button2"
        Me.Button2.TabIndex = 2
        Me.Button2.Text = "Button2"
        '
        'Label2
        '
        Me.Label2.ForeColor = System.Drawing.Color.White
        Me.Label2.Location = New System.Drawing.Point(116, 52)
        Me.Label2.Name = "Label2"
        Me.Label2.TabIndex = 3
        Me.Label2.Text = "Label2"
        '
        'Label3
        '
        Me.Label3.Location = New System.Drawing.Point(64, 92)
        Me.Label3.Name = "Label3"
        Me.Label3.TabIndex = 4
        Me.Label3.Text = "Label3"
        '
        'frmColorButtons
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(234, 125)
        Me.Controls.Add(Me.Label3)
        Me.Controls.Add(Me.Label2)
        Me.Controls.Add(Me.Button2)
        Me.Controls.Add(Me.Button1)
        Me.Controls.Add(Me.Label1)
        Me.Name = "frmColorButtons"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
 
    End Sub
#End Region
    Private overLabel As Boolean = False
    Private LabelBorderColor As Color = Color.Red
    Private Sub Label1_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label1.MouseEnter
        overLabel = True
        Label1.Tag = Label1.BackColor
        Label1.BackColor = Color.Cyan
    End Sub
    Private Sub Label1_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label1.MouseLeave
        overLabel = False
        Label1.BackColor = Label1.Tag
    End Sub
    Private Sub Label1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Label1.Paint
        If overLabel Then
            Dim g As Graphics = e.Graphics
            Dim p As New Pen(LabelBorderColor)
            g.DrawRectangle(p, 0, 0, Label1.Width - 1, Label1.Height - 1)
            p.Dispose()
        End If
    End Sub
    Private Sub Label1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label1.Click
        If Me.Label1.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft Then
            Me.Label1.ImageAlign = System.Drawing.ContentAlignment.MiddleRight
        Else
            Me.Label1.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft
        End If
    End Sub
    Private Sub Button1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Button1.Paint
 
        Dim borderWidth As Integer = 1
        Dim BorderColor As Color
 
        If bMouseInButton = True Then
            MyBase.OnPaint(e)
            BorderColor = Me.BackColor 'Color.Blue
            ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, BorderColor, borderWidth, ButtonBorderStyle.Solid, BorderColor, borderWidth, ButtonBorderStyle.Solid, BorderColor, borderWidth, ButtonBorderStyle.Solid, BorderColor, borderWidth, ButtonBorderStyle.Solid)
        Else
            MyBase.OnPaint(e)
            BorderColor = Me.BackColor
            ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, BorderColor, borderWidth, ButtonBorderStyle.Solid, BorderColor, borderWidth, ButtonBorderStyle.Solid, BorderColor, borderWidth, ButtonBorderStyle.Solid, BorderColor, borderWidth, ButtonBorderStyle.Solid)
        End If
    End Sub
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        If bHit = False Then
            Button2.BackColor = System.Drawing.Color.Red
            bHit = True
        Else
            Button2.BackColor = RestoreBackColor
            bHit = False
        End If
        Dim o As New Buttons.clsDialogColor
        o.PickAColor()
    End Sub
    Private Sub frmColorButtons_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        RestoreBackColor = Button2.BackColor
    End Sub
    Private Sub Label2_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label2.MouseEnter
        ' Label2.BackColor = MixColors(x, x2, 50) 'middle
        Label2.BackColor = MixColors(x, x2, 20) 'more red
    End Sub
    Private Sub Label2_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label2.MouseLeave
        Label2.BackColor = MixColors(x, x2, 70) 'more blue
    End Sub
    Public Function MixColors(ByVal Color1 As Color, ByVal Color2 As Color, ByVal Percentage As Integer) As Color
        Dim R(1) As Byte, G(1) As Byte, B(1) As Byte
        Dim iR(1) As Integer, iG(1) As Integer, iB(1) As Integer
        Dim fRed As Integer, fGreen As Integer, fBlue As Integer
        Dim fPercentage(2) As Double
        If Percentage < 0 Then Percentage = 0
        If Percentage > 100 Then Percentage = 100
 
        R(0) = Color1.R
        G(0) = Color1.G
        B(0) = Color1.B
        R(1) = Color2.R
        G(1) = Color2.G
        B(1) = Color2.B
        If R(0) > R(1) Then
            iR(0) = -1
            iR(1) = R(0) - R(1)
        Else
            iR(0) = 1
            iR(1) = R(1) - R(0)
        End If
 
        fPercentage(0) = (iR(1) / 100) * (Percentage * iR(0))
        If G(0) > G(1) Then
            iG(0) = -1
            iG(1) = G(0) - G(1)
        Else
            iG(0) = 1
            iG(1) = G(1) - G(0)
        End If
 
        fPercentage(1) = (iG(1) / 100) * (Percentage * iG(0))
        If B(0) > B(1) Then
            iB(0) = -1
            iB(1) = B(0) - B(1)
        Else
            iB(0) = 1
            iB(1) = B(1) - B(0)
        End If
 
        fPercentage(2) = (iB(1) / 100) * (Percentage * iB(0))
        fRed = R(0) + fPercentage(0)
        fGreen = G(0) + fPercentage(1)
        fBlue = B(0) + fPercentage(2)
 
        Dim newcol As Color = Color.FromArgb(fRed, fGreen, fBlue)
        Return newcol
    End Function
    Private Sub Label3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label3.Click
        MessageBox.Show("click")
        Label3.Focus()
 
    End Sub
    Private Sub LabelEx_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label2.MouseDown, Label3.MouseDown
        Dim lbl As LabelEx = DirectCast(sender, LabelEx)
 
        If Not IsNothing(lastPressedLabel) Then
            lastPressedLabel.setlook(Border3DStyle.Adjust)
        End If
 
        lbl.setlook(Border3DStyle.Sunken)
        lastPressedLabel = lbl
 
    End Sub
 
End Class
 
'CLASS
Public Class LabelEx
    Inherits Windows.Forms.Label
    Private look As Border3DStyle
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        Dim rc As New Rectangle(0, 0, MyBase.Width, MyBase.Height)
        ControlPaint.DrawBorder3D(e.Graphics, rc, look)
    End Sub
    Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
        MyBase.OnMouseEnter(e)
        If look <> Border3DStyle.Sunken Then
            look = Border3DStyle.Raised
            MyBase.Refresh()
        End If
    End Sub
    Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
        MyBase.OnMouseLeave(e)
        If look <> Border3DStyle.Sunken Then
            look = Border3DStyle.Adjust
            MyBase.Refresh()
        End If
    End Sub
    Public Sub setlook(ByVal newlook As Border3DStyle)
        look = newlook
        MyBase.Refresh()
    End Sub
End Class

Open in new window

0
Fernando SotoRetiredCommented:
Hi bertpet;

Any time you want to change the look and fell of a control you really need to sub-class it in stead of doing it in the project. The sample code below is something I started to play with after reading your question.

Fernando
The file MyButton.Designer.VB
=====================================================================
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class MyButton
    Inherits System.Windows.Forms.Button
 
    'Control overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub
 
    'Required by the Control Designer
    Private components As System.ComponentModel.IContainer
 
    ' NOTE: The following procedure is required by the Component Designer
    ' It can be modified using the Component Designer.  Do not modify it
    ' using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        components = New System.ComponentModel.Container()
    End Sub
 
End Class
=====================================================================
 
The MyButton.VB
=====================================================================
Imports System.Drawing
Imports System.Drawing.Drawing2D
 
Public Class MyButton
 
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
 
        ' Calling the base class OnPaint
        MyBase.OnPaint(e)
        ' Setup the Formatting for the text
        Dim formatText As StringFormat = New StringFormat(StringFormatFlags.NoClip)
        formatText.LineAlignment = StringAlignment.Center
        formatText.Alignment = StringAlignment.Center
        ' Drawing the button yoursel. 
        Dim lgBrush As LinearGradientBrush
        ' Draw gradient in different state Clicked and un-clicked
        If IsClicked Then
            ' Mouse clicked state
            lgBrush = New LinearGradientBrush(New Rectangle(0, 0, Me.Width, Me.Height), Color.FromArgb(190, 190, 190), _
                Color.White, LinearGradientMode.Vertical)
        Else
            ' Mouse not clicked state
            lgBrush = New LinearGradientBrush(New Rectangle(0, 0, Me.Width, Me.Height), Color.White, _
                Color.FromArgb(190, 190, 190), LinearGradientMode.Vertical)
        End If
        e.Graphics.FillRectangle(lgBrush, e.ClipRectangle)
        ' Draw the line around the button
        e.Graphics.DrawRectangle(New Pen(Color.Black, 1), 0, 0, Me.Width - 1, Me.Height - 1)
        ' Draw focus rectangle
        If HasFocus Then
            Dim focusRect As Rectangle = New Rectangle(2, 2, Me.Width - 5, Me.Height - 5)
            Dim fPen As New Pen(Color.Black, 1)
            fPen.DashStyle = DashStyle.Dot
            e.Graphics.DrawRectangle(fPen, focusRect)
        End If
        ' Draw the text in the button
        e.Graphics.DrawString(Me.Text, Me.Font, New SolidBrush(ForeColor), _
            New RectangleF(0.0F, 0.0F, Me.Width, Me.Height), formatText)
 
 
    End Sub
 
    Private IsClicked As Boolean = False
    Private HasFocus As Boolean = False
 
    ' Is the button being clicked and if so set variable for paint method
    Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseDown(e)
 
        IsClicked = True
        Me.Invalidate()
 
    End Sub
 
    ' If button not clicked reset the drawing variable
    Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseUp(e)
 
        IsClicked = False
        Me.Invalidate()
 
    End Sub
 
    ' Does the control have the focus if so set vaiable for paint event to 
    ' draw focus rectangle
    Protected Overrides Sub OnGotFocus(ByVal e As System.EventArgs)
        MyBase.OnGotFocus(e)
 
        HasFocus = True
        Me.Invalidate()
 
    End Sub
 
    ' If control does not have the focus reset variable
    Protected Overrides Sub OnLostFocus(ByVal e As System.EventArgs)
        MyBase.OnLostFocus(e)
 
        HasFocus = False
        Me.Invalidate()
 
    End Sub
 
    ' Set button focus when button is clicked.
    Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
        MyBase.OnClick(e)
 
        Me.Focus()
 
    End Sub
 
End Class
=======================================================================

Open in new window

0
Fernando SotoRetiredCommented:
Hi bertpet;

If you place the two files I posted in my last post in the project directory with your other code files and then add them to your project with the add existing item and then compile the file you will find the control in the Toolbox under the Tab that has your project name. Just drag the control onto a form and try it out.

Fernando
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
bertpetAuthor Commented:
Worked perfectly.  Thank you very much.
0
Fernando SotoRetiredCommented:
Not a problem, glad I was able to help. ;=)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.