Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Image Transition in VB.NET Windows Forms

0.00/5 (No votes)
8 Nov 2009 1  
Image transition and visual effects in VB.NET using GDI+.

Introduction

This article demonstrates how to implement a simple transition on images in VB.NET.

Transitions are one of the most useful features used in slide shows, business presentations, videos, screensavers, and with transitions, coders can build simple and easy visual effects on their web pages/Windows Forms/videos with simple and very minimal code.

Background

You may find a lot of articles that demonstrate how to implement image transitions using Silverlight or Dynamic HTML, but it's rare to find articles that talk about image transitions either in C# or VB.NET Windows Forms ...... apparently, image transitions are very good business.

In this article, I'll try to explain some of the most popular image transition methods and how they are done.

Transitions and Visual Effects

The list below shows the most popular image visual effects/transitions. You may follow the same transition names or rename the transitions to your convenience

  1. Barn: motion that resembles a doors opening or closing effect
  2. Blinds: motion that appears to open or close blinds
  3. CheckBoard: squares placed like a checker or chess board
  4. Iris: motion similar to opening of camera aperture
  5. Fade: fading out one or two images
  6. Slide: sliding sections or the whole image into place
  7. Spiral: spiral motion

Transitions Timing

The System.Threading.Timer class implements a simple light-weight timer that uses callback functions, and yes, it only has a few features, but it also has some nice benefits such as a way to specify the callback, a way to specify the time to wait before the first time the callback is run, and a way to specify the period between calls. These are very important to have an upper hand over the speed of GDI+ during transitions and to calculate a transition's steps.

Also, some people may prefer to use the System.Timers.Timer class instead of the System.Threading.Timer class and hook up the Elapsed event for the Timer class to accelerate GDI+.

The following simple code illustrates how to use the System.Timers class to draw something on the form:

  • Declare timer:
  • Private m_timer As New System.Timers.Timer()
  • Hook up the Elapsed event for the timer and enable the timer (the StartTimer routine):
  • Private Sub StartTimer(ByVal m_Interval As Integer)
        AddHandler m_timer.Elapsed, AddressOf TimerTick
        m_timer.Interval = m_Interval
        m_timer.Enabled = True
    End Sub
  • Specify what you want to happen when the Elapsed event is raised:
  • Private Sub TimerTick(ByVal source As Object, _
                          ByVal e As System.Timers.ElapsedEventArgs)
        Invalidate()
    End Sub
  • Draw something in the Paint event:
  • Private Sub Form2_Paint(ByVal sender As System.Object, _
                            ByVal e As PaintEventArgs) Handles MyBase.Paint
    
        Dim path As New Drawing2D.GraphicsPath()
        Dim stringText As String = Date.Now
        Dim family As New FontFamily("Verdana")
        Dim myfontStyle As Integer = CInt(FontStyle.Bold)
        Dim emSize As Integer = 20
        Dim origin As New Point(0, 0)
        Dim format As StringFormat = StringFormat.GenericDefault
        path.AddString(stringText, family, myfontStyle, emSize, origin, format)
    
        Using lgb As New Drawing2D.LinearGradientBrush(path.GetBounds(), _
                                                       Color.Cyan, Color.Blue, 90, 0)
            e.Graphics.FillPath(lgb, path)
        End Using
    End Sub
  • Pass the StartTime routine to the Form Load event and run:
  • Private Sub Form2_Load(ByVal sender As System.Object, _
                            ByVal e As System.EventArgs) Handles MyBase.Load
        StartTimer(1000)
    End Sub

The following code illustrates how to use System.Threading.Timer to draw something on the form by following the same steps above:

Public Class Form1

    Private ThreadTimer As System.Threading.Timer

    Private Sub StartTimer(ByVal Interval As Integer)
        Dim CallBackTimer As New Threading.TimerCallback(AddressOf TimerTick)
        ThreadTimer = New System.Threading.Timer(CallBackTimer, Nothing, 0, Interval)
    End Sub

    ' ........ rest of the code as explained before

End Class

Barn Visual Effect

The following code example illustrates how to apply a simple vertical Barn transition:

  • Declare variables such as the timer, transition steps, and starting time:
  • Public Class frmTransition
    
        Private m_timer As New System.Timers.Timer()
        Private m_Steps As Single
        Private m_startTime As DateTime
    
        ' .......... rest of code
    
    End Class
  • Hook up the Elapsed event for the timer, initialize the variables, and enable the timer (the StartTimer routine):
  • Private Sub StartTimer(ByVal m_Interval As Integer)
        AddHandler m_timer.Elapsed, AddressOf TimerTick
        m_timer.Interval = m_Interval
        m_timer.Enabled = True
        m_Steps = 0
        m_startTime = DateTime.Now
        Invalidate()
    
    End Sub
    ' .......... rest of code
  • Specify what you want to happen when the Elapsed event is raised. Define and calculate the elapsed time, define the animation time (the lowest the value, the highest the speed), calculate the transition steps and invalidate the paint:
  • Private Sub TimerTick(ByVal source As Object, _
                          ByVal e As System.Timers.ElapsedEventArgs)
    
        ' define & calculate ellapsed time
        Dim timeEllapsed As TimeSpan = DateTime.Now - m_startTime
        ' define animation time
        'the lowest the value the highest the speed
        Dim AnimationTime As Integer = 2
        ' calcualte transition steps
        m_Steps = CSng((100.0F / AnimationTime * timeEllapsed.TotalSeconds))
        ' check transition steps value & fix it
        If m_Steps > 100 Then
            m_Steps = 100
        End If
        ' invalidate the paint
        Invalidate()
    
    End Sub
    ' .......... rest of code

To draw the transition effect, follow these steps:

  1. Define a transition bitmap.
  2. Define a transition rectangle.
  3. Draw the top part Barn effect by defining the top part of the destination rectangle. Define the image top part source rectangle and then draw the top part of the image.
  4. Repeat step 3 to draw the bottom part of the Barn effect by defining the destination rectangle bottom part. Define the image's bottom part source rectangle and then draw the bottom part of the image.
  5. Private Sub frmTransition_Paint(ByVal sender As Object, _
                                    ByVal e As PaintEventArgs) _
                                    Handles MyBase.Paint
    
        ' define transition bitmap
        Dim bmp As New Bitmap(My.Resources.baby_5)
    
        ' define transition rectangle
        Dim m_rect As New Rectangle(0, 0, 100, 100)
    
        ' draw the top part barns effect 
        ' draw the top part of the image based on transition steps
    
        ' define the top part of destination rectangle
        Dim destTopRect As New Rectangle(0, 0, m_rect.Width, _
                        CInt(m_rect.Height * m_Steps / 200))
    
        ' define the image top part source rectangle
        Dim srcTopRect As New Rectangle(0, 0, bmp.Width, CInt(bmp.Height / 2))
    
        ' draw the top part of the image
        e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)
    
    
        ' let us repeat the steps above to draw the bottom part of the barns effect
    
        ' define the destination rectangle bottom part
        Dim destBottomRect As New Rectangle(0, _
            CInt(m_rect.Height - CInt(m_rect.Height * m_Steps / 200)), _
            m_rect.Width, _
            CInt((m_rect.Height * m_Steps / 200)))
        ' define the image's bottom part source rectangle
        Dim srcBottomRect As New Rectangle(0, CInt(bmp.Height / 2), _
                                           bmp.Width, CInt(bmp.Height / 2))
    
        ' draw the bottom part of the image
        e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)
    
    End Sub
  6. Pass the StartTime routine to the Form Load event and run.
  7. Set the time interval to 60 milliseconds.
  8. To get better performance, I believe the interval value should not exceed 100 milliseconds. The smaller the value, the better the performance.
  9. Private Sub frmTransition_Load(ByVal sender As Object, _
                                   ByVal e As EventArgs) Handles MyBase.Load
        StartTimer(60)
    End Sub

The following code example illustrates how to apply a horizontal Barn transition:

Private Sub frmTransition_Paint(ByVal sender As Object, _
                                ByVal e As PaintEventArgs) Handles MyBase.Paint

    Dim bmp As New Bitmap(My.Resources.baby_5)
    Dim m_rect As New Rectangle(0, 0, 100, 100)

    ' draw the left part barns effect 
    Dim destTopRect As New Rectangle(0, 0, _
        CInt(m_rect.Width * m_Steps / 200), m_rect.Height)
    Dim srcTopRect As New Rectangle(0, 0, CInt(bmp.Width / 2), bmp.Height)
    e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)

    ' draw the right part barns effect
    Dim destBottomRect As New Rectangle(_
        CInt(m_rect.Width - CInt(m_rect.Width * m_Steps / 200)), _
        0, _
        CInt((m_rect.Width * m_Steps / 200)), _
        m_rect.Height)
    Dim srcBottomRect As New Rectangle(CInt(bmp.Width / 2), 0, _
                                       CInt(bmp.Width / 2), bmp.Height)

    e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)

End Sub

What will happen if we mix between the above two Barn visual effects (horizontal and vertical effects).......!!!??? We will get a different effect ....... you may call it Barns Boom!

The following code example illustrates how to apply a Barns Boom transition:

Private Sub frmTransition_Paint(ByVal sender As Object, _
                                ByVal e As PaintEventArgs) Handles MyBase.Paint

    Dim bmp As New Bitmap(My.Resources.baby_5)
    Dim m_rect As New Rectangle(0, 0, 100, 100)

    ' ------------------------------------------------------->
    ' draw the left part of the barn
    Dim destLeftRect As New Rectangle(0, 0, _
                        CInt(m_rect.Width * m_Steps / 200), m_rect.Height)
    Dim srcLeftRect As New Rectangle(0, 0, CInt(bmp.Width / 2), bmp.Height)
    e.Graphics.DrawImage(bmp, destLeftRect, srcLeftRect, GraphicsUnit.Pixel)

    ' ------------------------------------------------------->
    ' draw the right part of the barn
    Dim destRightRect As New Rectangle(_
                CInt(m_rect.Width - CInt(m_rect.Width * m_Steps / 200)), _
                0, _
                CInt((m_rect.Width * m_Steps / 200)), _
                m_rect.Height)
    Dim srcRightRect As New Rectangle(CInt(bmp.Width / 2), 0, _
                                       CInt(bmp.Width / 2), bmp.Height)
    e.Graphics.DrawImage(bmp, destRightRect, srcRightRect, GraphicsUnit.Pixel)

    ' ------------------------------------------------------->
    ' draw the top part of the barn
    Dim destTopRect As New Rectangle(0, 0, m_rect.Width, _
                    CInt(m_rect.Height * m_Steps / 200))
    Dim srcTopRect As New Rectangle(0, 0, bmp.Width, CInt(bmp.Height / 2))
    e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)

    ' ------------------------------------------------------->
    ' draw the bottom part of the barn
    Dim destBottomRect As New Rectangle(0, _
                        CInt(m_rect.Height - CInt(m_rect.Height * m_Steps / 200)), _
                        m_rect.Width, _
                        CInt((m_rect.Height * m_Steps / 200)))
    Dim srcBottomRect As New Rectangle(0, CInt(bmp.Height / 2), _
                                       bmp.Width, CInt(bmp.Height / 2))

    e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)

End Sub

Rotate, Maximize, and Spin Visual Effect

The Drawin2D.Matrix class plays an important role in transition effects such as rotate, maximize, and spin of an image, and the following steps highlight the main points used in the Maximize visual effect:

  1. Define the transition bitmap
  2. Define the transition rectangle
  3. Define and calculate the transition scale factor used in the matrix
  4. Define the matrix class and pass the scale factor to it, the effect will start from the rectangle mid-point
  5. Pass the matrix to the graphics and draw the effect

The following code example illustrates how to apply the Maximize transition:

Private Sub frmTransition_Paint(ByVal sender As Object, _
                                ByVal e As PaintEventArgs) Handles MyBase.Paint

    ' draw maximize effect
    Dim bmp As New Bitmap(My.Resources.baby_5)
    Dim m_rect As New Rectangle(0, 0, 150, 150)

    ' define and calculate transition scale factor used in the matrix
    Dim sf As Single = m_Steps / 100
    If sf = 0 Then
        sf = 0.01F
    End If
    ' define the matrix class & pass the scale factor to it
    ' effect will strat from the rectangle mid-point
    Dim mx As New Drawing2D.Matrix(sf, 0, 0, sf, m_rect.Width / 2, m_rect.Height / 2)
    ' pass the matrix to graphics
    e.Graphics.Transform = mx
    Dim destRect As New Rectangle(-m_rect.Width / 2, -m_rect.Height / 2, _
                                  m_rect.Width, m_rect.Height)
    Dim srcRect As New Rectangle(0, 0, bmp.Width, bmp.Height)
    e.Graphics.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel)

End Sub

The following steps highlight the main points used with the Rotate and Spin visual effect:

  1. Define the transition bitmap
  2. Define the transition rectangle
  3. Define and calculate the transition scale factor used in the matrix
  4. Define the matrix class and pass the scale factor to it, the effect will start from the rectangle mid-point
  5. Define the rotation factor
  6. Pass the rotation factor to the matrix to rotate the matrix and set the Drawing2D.MatrixOrder value to Append (for Spin effect, just set the Drawing2D.MatrixOrder value to Prepend)
  7. Pass the matrix to the graphics and draw the effect
Private Sub frmTransition_Paint(ByVal sender As Object, _
                                ByVal e As PaintEventArgs) _
                                Handles MyBase.Paint

    ' draw maximize effect
    Dim bmp As New Bitmap(My.Resources.baby_5)
    Dim m_rect As New Rectangle(0, 0, 150, 150)

    ' define and calculate transition scale factor used in the matrix
    Dim sf As Single = m_Steps / 100
    If sf = 0 Then
        sf = 0.01F
    End If
    ' define the matrix class & pass the scale factor to it
    ' effect will strat from the rectangle mid-point
    Dim mx As New Drawing2D.Matrix(sf, 0, 0, sf, _
                  m_rect.Width / 2, m_rect.Height / 2)
    ' pass the matrix to graphics
    ' define rotation factor
    Dim rf As Single = m_Steps * 360 / 100

    ' pass the rotation factor to the matrix 
    ' to rotate the matrix and set the matrixorder
    ' for spin set MatrixOrder value to Prepend
    mx.Rotate(rf, Drawing2D.MatrixOrder.Append)

    e.Graphics.Transform = mx

    Dim destRect As New Rectangle(-m_rect.Width / 2, -m_rect.Height / 2, _
                                  m_rect.Width, m_rect.Height)
    Dim srcRect As New Rectangle(0, 0, bmp.Width, bmp.Height)
    e.Graphics.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel)

End Sub

For further details about other effects (there are about 28 effects waiting for you to play with), you may download the file attached to the article:

The Animation Control

  • Animation control files
    • AnimationTypes.vb: Public enum of about 28 visual effects/transitions
    • AnimationControl.vb: Extending the Control class
  • Control property
    • AnimationSpeed: used to set the animation speed; the greater the value, the slower the speed
    • AnimationType: used to set the Animationtypes enum
    • AnimatedImage: used to set the image required for the visual effect
    • AnimatedFadeImage: used to set the fade image which will be used with the animated image
    • Opacity, Transparent, TransparenColor: used to set the transparency of the control (for further details, you may refer to my earlier article about VB.NET translucent controls using GDI+, available in this link)

Using the Control

Build AnimationControl and use it in your forms. The following simple code illustrates how to use AnimationControl with Windows Forms:

Public Class TestForm

    Private bmp As New Bitmap(My.Resources.baby_5)

    Private Sub TestForm_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load
        AnimationControl1.AnimatedFadeImage = Panel1.BackgroundImage
        AnimationControl1.AnimatedImage = bmp
    End Sub

    Private Sub btnSpiarlBoom_Click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles btnSpiarlBoom.Click

        AnimationControl1.AnimationType = AnimationTypes.SpiralBoom
        AnimationControl1.Animate(40)

    End Sub

    ' rest of code 

End Class

Download the attached file, play with it, and you may add your own visual effects ....... it is simple and funny. Enjoy it.

History

  • 7th November, 2009: First release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here