WinForms VB.NET Picture Hover Button






4.04/5 (10 votes)
Hover button with picture and font that changes with MouseOver.
Introduction
This is a hover button/hover control, that allows for a lot of flexibility as far as look and feel is concerned. You can set the location of the text and the image, as well as the image that is shown when the mouse is over the control. The example uses a VB.NET WinForms UserControl
as the base for the control. If you're not experienced with building user controls then this is a great place to start. Looking at the guts of this control you'll learn some of the basics such as how to make a control a container for other controls, how to draw on the control using the Graphics
class.
Functionality
The control allows you to use it as a button, or just a container, or simply a hover control. The hovering effect is managed by way of a timer. This is more reliable than using the MouseLeave
or MouseEnter
events. Each of those events may or may not fire depending on the speed of the mouse over the control. So if you do not use a timer for handling the hover effects, you may end up with a control that has the hover effect applied, but it never goes away because the MouseLeave
event was never fired.
Capabilities
- Can be in a selected state with a selected color defined.
- Text
ForeColor
can be a specified color on Hover. - Image can be defined for Hover effect.
- Image can be defined for regular, or non-hover effects.
- Hover color can be defined. So the control's
BackColor
looks as if it has changed when the mouse is over the control. - Set the border color.
- Define whether to view the border or not.
- Define a group of buttons by setting the "
Group
" string value. This will select or unselect all the buttons with the same "Group
" value on the current parent container. - Select or unselect all the buttons on the same parent container.
- Position the text wherever you want on the control using the
ContentAlignment
enumeration as is currently used for theLabel
control. - Position the image anywhere on the control using the
ContentAlignment
enumeration as is currently used for theLabel
control. - Use the control as a container for other controls.
Construction
Add a UserControl
to your project. Set some of the initial Imports
statements as well as OPTION STRICT
, etc.
Option Strict On
Option Explicit On
Imports System.ComponentModel
Imports System.ComponentModel.Design
At the top of the class, add some attributes that define how the control operates:
' DefaultEvent("Click"), This sets the default event when double-clicking
' the control in design-mode.
' DefaultProperty("Text"), This will set the default
' property for the property inspector
' in design-mode.
'
' This attribute makes this control a container for
' other controls.
' Designer("System.Windows.Forms.Design.ParentControlDesigner,
System.Design", GetType(IDesigner))
'
<DESIGNER("SYSTEM.WINDOWS.FORMS.DESIGN.PARENTCONTROLDESIGNER,
DefaultProperty(?Text?) DefaultEvent(?Click?),
GetType(IDesigner)), _ System.Design?,> _
Public Class PictureHoverButton
Inherits System.Windows.Forms.UserControl
Next, in Sub New
, set the styles for the control. This manages how the control functions specifically in the area of how to draw the control and what it supports:
' This draws the control whenever it is resized
setstyle(ControlStyles.ResizeRedraw, True)
' This supports mouse movement such as the mouse wheel
setstyle(ControlStyles.UserMouse, True)
' This allows the control to be transparent
setstyle(ControlStyles.SupportsTransparentBackColor, True)
' This helps with drawing the control so that it doesn't flicker
Me.SetStyle(ControlStyles.DoubleBuffer _
Or ControlStyles.UserPaint _
Or ControlStyles.AllPaintingInWmPaint, _
True)
' This updates the styles
Me.UpdateStyles()
Override the OnPaint
event for the control. This is where the magic happens. This is where your control is your canvas, and you're the artist.
Protected Overrides Sub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(pe)
Dim TopMargin As Integer
Dim g As Graphics = pe.Graphics
Dim DrawHover As Boolean
_HoverRectangle = Nothing
_HoverRectangle = New Rectangle(0, 0, Me.Width, Me.Height)
' The mouse is hovering over the control
If _HasFocus Then
If Me.Selected Then
Dim rec As New Rectangle(0, 0, Me.Width, Me.Height)
Dim b As New SolidBrush(Me.SelectedColor)
g.FillRectangle(b, rec)
Else
' Make sure the color is not Nothing, or Empty
' which is the equivalent to nothing for a color.
If Not HoverColor.Equals(Color.Empty) Then
Dim rec As New Rectangle(0, 0, Me.Width, Me.Height)
Dim b As New SolidBrush(Me.HoverColor)
g.FillRectangle(b, rec)
End If
End If
' Draw the Hover image
If Not Me.Selected Then
DrawHover = True
End If
Else
If Me.Selected Then
Dim rec As New Rectangle(0, 0, Me.Width, Me.Height)
Dim b As New SolidBrush(Me.SelectedColor)
g.FillRectangle(b, rec)
End If
End If
Dim ptImage As Point
' Used to hold the dimensions of the current image
Dim iWidth As Integer
Dim iHeight As Integer
Dim iCenter As Integer
If DrawHover Then
If Not Me.HoverImage Is Nothing Then
iWidth = Me.HoverImage.Width
iHeight = Me.HoverImage.Height
Else
If Not Me.Image Is Nothing Then
iWidth = Me.Image.Width
iHeight = Me.Image.Height
End If
End If
Else
If Not Me.Image Is Nothing Then
iWidth = Me.Image.Width
iHeight = Me.Image.Height
End If
End If
' Make sure we even need to draw an image to begin
' with. There may not be any images in this control.
If Not iHeight = 0 Then
' Ge the position of the image
Select Case ImageAlign
Case ContentAlignment.BottomCenter
ptImage =
New Point(Convert.ToInt32((Me.Width / 2) - (iWidth / 2)),
(Me.Height - iHeight) - 3)
Case ContentAlignment.BottomLeft
ptImage = New Point(5, (Me.Height - iHeight) - 3)
Case ContentAlignment.BottomRight
ptImage = New Point((Me.Width - iWidth) - 5,
(Me.Height - iHeight) - 3)
Case ContentAlignment.MiddleCenter
ptImage =
New Point(Convert.ToInt32((Me.Width / 2) - (iWidth / 2)),
Convert.ToInt32((Me.Height / 2) - (iHeight / 2)))
Case ContentAlignment.MiddleLeft
ptImage =
New Point(5, Convert.ToInt32((Me.Height / 2) - (iHeight / 2)))
Case ContentAlignment.MiddleRight
ptImage = New Point((Me.Width - iWidth) - 5,
Convert.ToInt32((Me.Height / 2) - (iHeight / 2)))
Case ContentAlignment.TopCenter
ptImage =
New Point(Convert.ToInt32((Me.Width / 2) - (iWidth / 2)), 5)
Case ContentAlignment.TopLeft
ptImage = New Point(5, 5)
Case ContentAlignment.TopRight
ptImage = New Point((Me.Width - iWidth) - 5, 5)
End Select
If DrawHover Then
If Not Me.HoverImage Is Nothing Then
g.DrawImage(Me.HoverImage, ptImage.X, ptImage.Y,
Me.HoverImage.Width, Me.HoverImage.Height)
Else
If Not Me.Image Is Nothing Then
g.DrawImage(Me.Image, ptImage.X, ptImage.Y,
Me.Image.Width, Me.Image.Height)
End If
End If
Else
If Not Me.Image Is Nothing Then
g.DrawImage(Me.Image, ptImage.X, ptImage.Y,
Me.Image.Width, Me.Image.Height)
End If
End If
End If
' Get the dimensions of the text.
' This will return a SizeF object that has height, width, etc.
Dim ptSize As SizeF = g.MeasureString(Text, Font)
Dim ptF As New PointF
' Get the location to set the Text.
Select Case Me.TextAlign
Case ContentAlignment.BottomCenter
ptF.Y = Me.Height
ptF.Y -= ptSize.Height
ptF.X = Convert.ToInt32(Me.Width / 2)
ptF.X -= ptSize.Width / 2
Case ContentAlignment.BottomLeft
ptF.Y = Me.Height
ptF.Y -= ptSize.Height
ptF.X = 2
Case ContentAlignment.BottomRight
ptF.Y = Me.Height
ptF.Y -= ptSize.Height
ptF.X = Me.Width
ptF.X -= ptSize.Width
Case ContentAlignment.MiddleCenter
ptF.Y = Convert.ToInt32(Me.Height / 2)
ptF.Y -= ptSize.Height / 2
ptF.X = Convert.ToInt32(Me.Width / 2)
ptF.X -= ptSize.Width / 2
Case ContentAlignment.MiddleLeft
ptF.Y = Convert.ToInt32(Me.Height / 2)
ptF.Y -= ptSize.Height / 2
ptF.X = 0
Case ContentAlignment.MiddleRight
ptF.Y = Convert.ToInt32(Me.Height / 2)
ptF.Y -= ptSize.Height / 2
ptF.X = Me.Width
ptF.X -= ptSize.Width
Case ContentAlignment.TopCenter
ptF.Y = 0
ptF.X = Convert.ToInt32(Me.Width / 2)
ptF.X -= ptSize.Width / 2
Case ContentAlignment.TopLeft
ptF.Y = 0
ptF.X = 0
Case ContentAlignment.TopRight
ptF.Y = 0
ptF.X = Me.Width
ptF.X -= ptSize.Width
End Select
If _HasFocus AndAlso Not Me.Selected Then
' Draw the Text for the control using the HoverForeColor
If Not Me.HoverForeColor.Equals(Color.Empty) Then
g.DrawString(Me.Text, Me.Font,
New SolidBrush(Me.HoverForeColor), ptF)
Else
g.DrawString(Me.Text, Me.Font,
New SolidBrush(Me.ForeColor), ptF)
End If
Else
' Draw the Text for the control
g.DrawString(Me.Text, Me.Font,
New SolidBrush(Me.ForeColor), ptF)
End If
' Draw the border
If Border Then
If Not BorderColor.Equals(Color.Empty) Then
Dim linePen As New Pen(New SolidBrush(_BorderColor), 1)
g.DrawRectangle(linePen, New Rectangle(0, 0, Me.Width - 1,
Me.Height - 1))
End If
End If
End Sub
Building custom or UserControl
s are fun and easy once you get the basics down. This control still has lots of room for improvement such as setting the hover or backcolor as gradient, etc.