Introduction
ImageButton Demo
ImageButtonBase
is custom button that uses image as design.
Background
To use an image as a button design, we cannot use the regular drawing method, the problem if we use the regular drawing method is, image will be blurred when the control size is larger than the normal size.
Left: Normal image before resized, Right: Image after resize to larger size.
To draw the image in order not to be blurred, the solution is to slice the image into 9 parts, and then draw the parts on the control.
9 segments button image.
Original Image
| |
Sliced Image |
|
Sliced image placement description.
Description | Image |
Top Left | |
Top Center | |
Top Right | |
Middle Left | |
Middle Center | |
Middle Right | |
Bottom Left | |
Bottom Center | |
Bottom Right | |
Slicing the Image
To slice the image into 9 parts, we have to crop the image. I use the function below to crop the image:
Private Function CropImage(ByVal sImage As Bitmap, _
ByVal x As Integer, ByVal y As Integer, _
ByVal w As Integer, ByVal h As Integer)
If w <= 0 Or h <= 0 Then
Return New Bitmap(1, 1)
End If
Dim bmp As New Bitmap(w, h)
bmp.SetResolution(96, 96)
Using g As Graphics = Graphics.FromImage(bmp)
g.DrawImageUnscaled(sImage, -x, -y)
End Using
Return bmp
End Function
In this project, I use class TileImages
to generate sliced images:
Public Class TileImages
Implements IDisposable
Public Sub New(ByVal img As Bitmap, ByVal column As Integer, ByVal row As Integer)
Me._SpritImage = img
_SpritImage.SetResolution(96, 96)
Me._Column = column
Me._Row = row
BuildList()
End Sub
Private lst As New List(Of Bitmap)
Private Sub BuildList()
lst.Clear()
If IsNothing(_SpritImage) Then
Return
End If
_ItemWidth = _SpritImage.Width / _Column
_ItemHeight = _SpritImage.Height / _Row
If _ItemWidth * _Column < _SpritImage.Width Then
_ItemWidth += 1
End If
If _ItemHeight * _Row < _SpritImage.Height Then
_ItemHeight += 1
End If
For r As Integer = 0 To _Row - 1
For c As Integer = 0 To _Column - 1
lst.Add(CropImage(_SpritImage, c * _ItemWidth, _
r * _ItemHeight, _ItemWidth, _ItemHeight))
Next
Next
End Sub
Public Function GetImage(ByVal row As Integer, _
Optional ByVal column As Integer = 0) As Bitmap
If row < 0 Or column < 0 Then
Return Nothing
End If
Return lst(row * _Column + column)
End Function
Private _SpritImage As Bitmap
Public Property SpritImage() As Bitmap
Get
Return _SpritImage
End Get
Set(ByVal value As Bitmap)
_SpritImage = value
If Not IsNothing(_spritImage)
_SpritImage.SetResolution(96, 96)
End If
BuildList()
Me.OnSpritImageChanged(EventArgs.Empty)
End Set
End Property
Public Event SpritImageChanged _
(ByVal sender As Object, ByVal e As System.EventArgs)
Protected Overridable Sub OnSpritImageChanged(ByVal e As System.EventArgs)
RaiseEvent SpritImageChanged(Me, e)
End Sub
Private _Column As Integer = 1
Public Property Column() As Integer
Get
Return _Column
End Get
Set(ByVal value As Integer)
_Column = value
BuildList()
Me.OnColumnChanged(EventArgs.Empty)
End Set
End Property
Public Event ColumnChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Protected Overridable Sub OnColumnChanged(ByVal e As System.EventArgs)
RaiseEvent ColumnChanged(Me, e)
End Sub
Private _Row As Integer = 1
Public Property Row() As Integer
Get
Return _Row
End Get
Set(ByVal value As Integer)
_Row = value
BuildList()
Me.OnRowChanged(EventArgs.Empty)
End Set
End Property
Public Event RowChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Protected Overridable Sub OnRowChanged(ByVal e As System.EventArgs)
RaiseEvent RowChanged(Me, e)
End Sub
Private _ItemWidth As Integer
Public ReadOnly Property ItemWidth() As Integer
Get
Return _ItemWidth
End Get
End Property
Private _ItemHeight As Integer
Public ReadOnly Property ItemHeight() As Integer
Get
Return _ItemHeight
End Get
End Property
Private Function CropImage(ByVal sImage As Bitmap, _
ByVal x As Integer, ByVal y As Integer, _
ByVal w As Integer, ByVal h As Integer)
If w <= 0 Or h <= 0 Then
Return New Bitmap(1, 1)
End If
Dim bmp As New Bitmap(w, h)
bmp.SetResolution(96, 96)
Using g As Graphics = Graphics.FromImage(bmp)
g.DrawImageUnscaled(sImage, -x, -y)
End Using
Return bmp
End Function
#Region " IDisposable Support "
Private disposedValue As Boolean = False
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
End If
lst.Clear()
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Drawing the Images
This control has 4 button states, and each state has an image:
The states:
State | Image |
Normal | |
Hover | |
Pressed | |
Active | |
To draw the image on control, firstly I draw a sliced image on a bitmap after control resize in method OnSizeChanged
that calls method GenenerateStrechedImage
(you can find this method in class RipsWareImageButtonBase
), then I use that bitmap to draw on the control.
Using the Code
Usage of RipsWareButtonBase
RipsWareImageButtonBase
is inheritance of RipsWareButtonBase
class, I create class RipsWareButtonBase for multipurpose button, so you can use this class to create your own button with your own drawing method.
The use of RipsWareButtonBase
:
Public Class TestButton
Inherits RipsWareButtonBase
Protected Overrides Sub DrawNormalState(ByRef g As System.Drawing.Graphics)
MyBase.DrawNormalState(g)
End Sub
Protected Overrides Sub DrawHoverState(ByRef g As System.Drawing.Graphics)
MyBase.DrawHoverState(g)
End Sub
Protected Overrides Sub DrawPressedState(ByRef g As System.Drawing.Graphics)
MyBase.DrawPressedState(g)
End Sub
Protected Overrides Sub DrawActiveState(ByRef g As System.Drawing.Graphics)
MyBase.DrawActiveState(g)
End Sub
Protected Overrides Sub DrawDisabledState(ByRef g As System.Drawing.Graphics)
MyBase.DrawDisabledState(g)
End Sub
End Class
Usage of RipsWareImageButtonBase
To use this control, you just drag the control into the form designer like the image above.
Project Structure
- ImageButton.sln
- RipsWareButtonBase.vb -
RipsWareButtonBase
button base class. - RipsWareImageButtonBase.vb -
RipsWareImageButtonBase
class - ImageButtonDesigner.vb - contains
ImageButtonBaseDesigner
for RipsWareImageButtonBase
designer.
- ImageButtonDemo.sln
History
References
- Rich Design Time Editing with UITypeEditors (VB.NET) by SSDiver2112 .