Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Image Button Base

4.89/5 (22 votes)
19 Jun 2012CPOL2 min read 64.6K   11.8K  
Create button from image

Introduction

Image_Button/Form1_2011-11-18_18-10-14.pngImage_Button/Image_Button_Demo_2011-11-18_10-28-53.png

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.

Normal Image Resized image
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

Image_Button/Normal5.png
Sliced Image
Image_Button/Segment_0_0.pngImage_Button/Segment_1_0.pngImage_Button/Segment_2_0.png
Image_Button/Segment_0_1.pngImage_Button/Segment_1_1.pngImage_Button/Segment_2_1.png
Image_Button/Segment_0_2.pngImage_Button/Segment_1_2.pngImage_Button/Segment_2_2.png

Sliced image placement description.

Description Image
Top Left Image_Button/Segment_0_0.png
Top Center Image_Button/Segment_1_0.png
Top Right Image_Button/Segment_2_0.png
Middle Left Image_Button/Segment_0_1.png
Middle Center Image_Button/Segment_1_1.png
Middle Right Image_Button/Segment_2_1.png
Bottom Left Image_Button/Segment_0_2.png
Bottom Center Image_Button/Segment_1_2.png
Bottom Right Image_Button/Segment_2_2.png

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:

VB.NET
''' <summary>
''' Crop image
''' </summary>
''' <param name="sImage">Source bitmap</param>
''' <param name="x">X location</param>
''' <param name="y">Y location</param>
''' <param name="w">Width</param>
''' <param name="h">Height</param>
''' <returns>Cropped image</returns>
''' <remarks></remarks>
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:

VB.NET
     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

        ''' <summary>
        ''' Zero base index
        ''' </summary>
        ''' <param name="row">Row of image with zero based index</param>
        ''' <param name="column">Column of image with zero based index</param>
        ''' <returns>Bitmap</returns>
        ''' <remarks></remarks>
        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

        ''' <summary>
        ''' Crop image
        ''' </summary>
        ''' <param name="sImage">Source bitmap</param>
        ''' <param name="x">X location</param>
        ''' <param name="y">Y location</param>
        ''' <param name="w">Width</param>
        ''' <param name="h">Height</param>
        ''' <returns>Cropped image</returns>
        ''' <remarks></remarks>
        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        ' To detect redundant calls

        ' IDisposable
        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposedValue Then
                If disposing Then
                    ' TODO: free unmanaged resources when explicitly called
                End If
                lst.Clear()
                ' TODO: free shared unmanaged resources
            End If
            Me.disposedValue = True
        End Sub

        ' This code added by Visual Basic to correctly implement the disposable pattern.
        Public Sub Dispose() Implements IDisposable.Dispose
            ' Do not change this code.  
            ' Put cleanup code in Dispose(ByVal disposing As Boolean) above.
            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 Image_Button/Normal5.png
HoverImage_Button/Hover5.png
PressedImage_Button/Pressed.png
ActiveImage_Button/Active5.png

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 :

VB.NET
Public Class TestButton
    Inherits RipsWareButtonBase

    Protected Overrides Sub DrawNormalState(ByRef g As System.Drawing.Graphics)
        MyBase.DrawNormalState(g)
        'Draw the normal image state here
    End Sub

    Protected Overrides Sub DrawHoverState(ByRef g As System.Drawing.Graphics)
        MyBase.DrawHoverState(g)
        'Draw the hover image state here
    End Sub

    Protected Overrides Sub DrawPressedState(ByRef g As System.Drawing.Graphics)
        MyBase.DrawPressedState(g)
        'Draw the pressed state here
    End Sub

    Protected Overrides Sub DrawActiveState(ByRef g As System.Drawing.Graphics)
        MyBase.DrawActiveState(g)
        'Draw the active or focused state here
    End Sub

    Protected Overrides Sub DrawDisabledState(ByRef g As System.Drawing.Graphics)
        MyBase.DrawDisabledState(g)
        'Draw the disable state here
    End Sub

End Class

Usage of RipsWareImageButtonBase

Image_Button/ImageButton_-_Microsoft_Visual_Basic_2005_Express_Edition_2011-11-18_22-18-52.png

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
    • Form1.vb - Test class

History

  • 01/11/2011 First created

References

  1. Rich Design Time Editing with UITypeEditors (VB.NET) by SSDiver2112 .

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)