Click here to Skip to main content
15,868,141 members
Articles / Programming Languages / C#
Article

AnimatedIcon Control

Rate me:
Please Sign up or sign in to vote.
4.63/5 (24 votes)
29 Jun 20043 min read 101.5K   5.1K   87   19
AnimatedIcon Control plays an animation as a sequence of images stored in the ImageList. The article demonstrates how to show an animated icon on the StatusBar.

AnimatedIcon Demo

Introduction

When I started to develop web-services, I examined the possibility to display current activity. For example, when an application is loading something from the Internet, you can show a sandy-glass or a progress bar. The progress bar is not good enough because the application does not know its real status: how much was loaded and how much is left. Sure, you can write an asynchronous monitor for getting real status but it heavily loads your web-service. Anyway, I wish I had a simple animation control to show animated icons on the StatusBar or wherever.

You know, there is an ImageAnimator class in the .NET Framework Library that displays animated GIF files. It doesn't suit me because:

  • I want to compose an animation from bitmaps during design time.
  • I would like to set speed for the animation.

That's why I wrote a small and simple control.

Inside the code

AnimatedIcon is a UserControl with a few properties and methods. Have a look at this class (some private members are hidden):

AnimatedIcon Class

Properties

Five properties define the look and behavior of the control:

  • ImageList

    ImageList contains images used to display the animation.

  • Delay

    Delay in milliseconds between the frames. Default value is 50 ms.

  • Pause

    Pause in milliseconds after every loop. Default value is 0.

  • LoopCount

    Number of loops to display. Default value is 0. It means infinite loop.

  • FirstFrame

    The first frame of the animation.

  • LastFrame

    The last frame of the animation.

The Pause property can be used to set a delay at the end of the loop (thank you, Tim, for the idea). FirstFrame and LastFrame are set to 0 and ImageList.Images.Count-1 respectively, by default. But you can set another range of frames for the animation. For example, if you added images to the ImageList to display some special state of the object or even yet another animation.

Methods

The methods are quite self explaining:

  • StartAnimation

    Starts animation from the beginning.

  • StopAnimation

    Stops animation.

  • ShowFrame

    Stops animation and displays the specified frame.

Code

StartAnimation creates a Thread that is responsible for the logic of the control. StopAnimation terminates this thread. threadFunc counts the frames and sends a signal to redraw the frame when it is changed.

C#
// Starts animation from the beginning.
public void StartAnimation()
{
   StopAnimation();
   CheckRange();  // Check the first and the last frames
   thread = new Thread( new ThreadStart( threadFunc ) );
   thread.IsBackground = true;
   thread.Start();
}

// Stops animation not changing current frame number.
public void StopAnimation()
{
   if( thread != null )
   {
      thread.Abort();
      thread = null;
   }
   currentLoop = 0;
}

// Displays the specified frame.
public void ShowFrame(int frame)
{
   StopAnimation();

   if( frame >= 0 && imageList != null
           && frame < imageList.Images.Count )
      currentFrame = frame;
   else
      currentFrame = 0;

   Refresh();
}

// Occurs when the control is redrawn.
protected override void OnPaint(PaintEventArgs e)
{
   // Draw a crossed rectangle if there is no frame to display

   if( imageList == null ||
      currentFrame < 0 ||
      currentFrame >= imageList.Images.Count )
   {
      if( this.Size.Width == 0 || this.Size.Height == 0 )
         return;

      Pen pen = new Pen( SystemColors.ControlText );
      e.Graphics.DrawRectangle( pen, 0, 0,
            this.Size.Width-1, this.Size.Height-1 );
      e.Graphics.DrawLine( pen, 0, 0,
                this.Size.Width, this.Size.Height );
      e.Graphics.DrawLine( pen, 0,
         this.Size.Height-1, this.Size.Width-1, 0 );
      pen.Dispose();
   }
   else
   {
      // Draw the current frame

      e.Graphics.DrawImage( imageList.Images[currentFrame],
                            0, 0, this.Size.Width, this.Size.Height );
   }
}

// The method to be invoked when the thread begins executing.
private void threadFunc()
{
   bool wasPause = false;
   currentFrame = firstFrame;

   while( thread != null && thread.IsAlive )
   {
      Refresh();                     // Redraw the current frame
      wasPause = false;

      if( imageList != null )
      {
         currentFrame++;
         if( currentFrame > lastFrame ||
             currentFrame >= imageList.Images.Count )
         {
            if( pause > 0 )          // Sleep after every loop
            {
               Thread.Sleep( pause );
               wasPause = true;
            }

            currentFrame = firstFrame;
            if( loopCount != 0 )     // 0 is infinitive loop
            {
               currentLoop++;
            }
         }
         if( loopCount != 0 && currentLoop >= loopCount )
         {
            StopAnimation();         // The loop is completed
         }
      }
      if( !wasPause ) // That prevents summation (pause + delayInterval)
         Thread.Sleep( delayInterval );
   }
}

Using the AnimatedIcon

First of all, you should add the AnimatedIcon control to the Toolbox in your Visual Studio .NET IDE. To do that, you should:

  • Right-click on the "Windows Forms" tab in the Toolbox.
  • Select "Add/Remove Items...".
  • On ".NET Framework Components", press the "Browse..." button, and find the AnimatedIcon.dll.

New AnimatedIcon control will be added to the Toolbox:

Toolbox

Now, you can drag this control from the Toolbox to your Form. That will create a new AnimatedIcon object in your project. By default, its ImageList is empty, and the control is displayed as a crossed square. Select this object and modify its properties: set the ImageList that contains a sequence of frames, set delay and the loop counter.

Properties

Don't forget to call the StartAnimation() method somewhere. Compile your project and enjoy!

AnimatedIcon on the StatusBar

If you run my demo, you will see a small animated icon on the StatusBar. I'll tell you how to do that. It cannot be done in the Designer, but it's very easy to do manually. First, create a private member in your Form class:

C#
private AnimatedIcon.AnimatedIcon animatedIcon2;

Then add a few lines to the constructor of the Form:

C#
public Form1()
{
   InitializeComponent();

   // This code adds the AnimatedIcon to the StatusBar

   this.animatedIcon2 = new AnimatedIcon.AnimatedIcon();
   this.animatedIcon2.Delay = 200;
   this.animatedIcon2.ImageList = this.imageList2;
   this.animatedIcon2.Name = "animatedIcon2";
   this.animatedIcon2.TabStop = false;
   this.animatedIcon2.Location = new Point(190,
       (statusBar1.Height - animatedIcon2.Size.Height)/2);

   statusBar1.Controls.Add(this.animatedIcon2);
   this.animatedIcon2.StartAnimation();
}

This code adds the AnimatedIcon object to the collection of controls contained within the StatusBar. Note, my StatusBarPanel with the text "Yet another..." is 180 units wide. That's why the left corner of the this.animatedIcon2 is 190 units:

C#
this.animatedIcon2.Location = new Point(190,
     (statusBar1.Height - animatedIcon2.Size.Height)/2);

I hope it was not difficult. Have a nice animation!

History

  • June 18, 2004 - First release.
  • June 28, 2004 - Version 1.1.

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


Written By
Latvia Latvia
Jevgenij lives in Riga, Latvia. He started his programmer's career in 1983 developing software for radio equipment CAD systems. Created computer graphics for TV. Developed Internet credit card processing systems for banks.
Now he is System Analyst in Accenture.

Comments and Discussions

 
GeneralNot working....(Testing Fail) Pin
Kumaran Jeyasingam24-Nov-08 17:49
Kumaran Jeyasingam24-Nov-08 17:49 
GeneralRequest for C#2008 version Pin
UltraWhack13-Jun-08 5:15
UltraWhack13-Jun-08 5:15 
NewsCross-thread operation avoid by using BackgroundWorker Pin
mruth0627-Dec-06 5:45
mruth0627-Dec-06 5:45 
GeneralNot Thread Safe Pin
SalizarMarxx14-Aug-06 16:18
SalizarMarxx14-Aug-06 16:18 
This is a great starting point, how ever there are several issues with the threading that is implemented in this conrtol, as a number of users have pointed out.
With out the use of Delegates for thread call backs the control will never be thread safe.

The only time your worker thread needs to abort is on dispose, but I would be carefull, calling the abort method will throw a none catchable ThreadAbortException, which is a bit nasty.
By Adding a Property or method to gracefully abort the thread this can be easily avoid.
Simply have your thread loop check for your property and then stop execution, once the method that was called in your thread start goes out of scoop so does your thread.

The OnPaint override call has a bit of odd logic in it as well, the check for size is enbedded within the Pen drawning clause. By moving this up and out of this if statement, you can avoid a needless call to Drawimage, and a call to your image list.

The Pause Frame is a nice idea, this can be expanded on by using a hashtable or other collection, hash prefered as you can have out of order keys, to control your pausing. this would allow greater conrtol of the animation.
GeneralThreadAbortedException Pin
Monsieur Noir5-Jul-06 4:44
Monsieur Noir5-Jul-06 4:44 
GeneralAnimate Titlebar's Icon Pin
Darkman11-Apr-06 11:50
Darkman11-Apr-06 11:50 
GeneralBlueing Control??! Weird... Pin
sfielden18-Aug-05 3:43
sfielden18-Aug-05 3:43 
GeneralRe: Blueing Control??! Weird... Pin
sfielden18-Aug-05 4:03
sfielden18-Aug-05 4:03 
GeneralGood Idea ^_^ Pin
eRRaTuM31-May-05 7:20
eRRaTuM31-May-05 7:20 
GeneralBuild and Run error Pin
LiamD13-Apr-05 5:44
LiamD13-Apr-05 5:44 
GeneralRe: Build and Run error Pin
Jevgenij Pankov13-Apr-05 21:41
Jevgenij Pankov13-Apr-05 21:41 
Generalreuse of code in commercial product Pin
molloyr19-Jan-05 22:33
molloyr19-Jan-05 22:33 
GeneralRe: reuse of code in commercial product Pin
Jevgenij Pankov20-Jan-05 4:35
Jevgenij Pankov20-Jan-05 4:35 
GeneralNice work, but .. Pin
Klaus Weisser22-Jun-04 20:04
Klaus Weisser22-Jun-04 20:04 
GeneralRe: Nice work, but .. Pin
Robert Rohde22-Jun-04 21:57
Robert Rohde22-Jun-04 21:57 
GeneralRe: Nice work, but .. Pin
darXstar18-Jul-05 7:57
darXstar18-Jul-05 7:57 
GeneralNice Work Pin
Mr Smiley22-Jun-04 13:38
Mr Smiley22-Jun-04 13:38 
GeneralHmmm Pin
Maximilian Hänel22-Jun-04 2:06
Maximilian Hänel22-Jun-04 2:06 
GeneralRe: Hmmm Pin
Dimitris Vasiliadis22-Jun-04 3:09
Dimitris Vasiliadis22-Jun-04 3:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.