
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 the Label
control.
- Position the image anywhere on the control using the
ContentAlignment
enumeration as is currently used for the Label
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:
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:
setstyle(ControlStyles.ResizeRedraw, True)
setstyle(ControlStyles.UserMouse, True)
setstyle(ControlStyles.SupportsTransparentBackColor, True)
Me.SetStyle(ControlStyles.DoubleBuffer _
Or ControlStyles.UserPaint _
Or ControlStyles.AllPaintingInWmPaint, _
True)
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)
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
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
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
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
If Not iHeight = 0 Then
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
Dim ptSize As SizeF = g.MeasureString(Text, Font)
Dim ptF As New PointF
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
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
g.DrawString(Me.Text, Me.Font,
New SolidBrush(Me.ForeColor), ptF)
End If
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.