Click here to Skip to main content
15,890,557 members
Articles / Multimedia / GDI+
Article

How to write a loading circle animation in .NET?

Rate me:
Please Sign up or sign in to vote.
4.92/5 (212 votes)
15 Feb 2007CPOL3 min read 762.7K   38.5K   480   173
A new kind of progress bar for .NET 2.0.

Sample Image - mrg_loadingcircle.jpg

Introduction

When it's time to wait, we are used to seeing the classic blue progress bar. It is everywhere in Windows and many other applications. However, animations are getting more and more popular.

For example, when Firefox loads a page, a small spinning circle appears and shows you that the page is loading. Moreover, Microsoft also uses this kind of animation in the Windows Media Center, Encarta 2006, SQL Server Management Studio Express, etc.

So, why don't we use this concept to show to our users that our application is working and/or loading? Let's begin by the presentation of the component I developed.

Points of interest

Rotation speed

The LoadingCircle uses a timer, and it has two responsibilities: to determine the color of the next spoke, and to redraw the circle at a specified number of milliseconds. When you use the property RotationSpeed, you modify the timer's property named Interval. Higher the value is, slower will be the rotation. The default rotation speed is 80, so at every 80 milliseconds, the circle will be redrawn.

How to draw a spoke?

First of all, we need coordinates for each spoke. We use the function DrawLine of GDI+, which needs two points, the beginning and the end of the line.

So, let's review some simple math notions. In order to draw a perfect circle, you have to know the following trigonometry concept: the cosines of an angle in degrees give us the X and the sine gives us the Y.

The method GetCoordinate computes, for a specified radius and angle, the coordinates of a point.

C#
private PointF GetCoordinate(PointF _objCircleCenter, 
               int _intRadius, double _dblAngle)
{
      PointF objPoint = new PointF();
      double dblAngle = Math.PI * _dblAngle / NUMBER_OF_DEGREES_HALF_CIRCLE;
      objPoint.X = _objCircleCenter.X + _intRadius * (float)Math.Cos(dblAngle);
      objPoint.Y = _objCircleCenter.Y + _intRadius * (float)Math.Sin(dblAngle);
      return objPoint;
}

The method DrawLine uses the coordinates computed by GetCoordinate, and draws a line with the two specified points and a color. Of course, we have to pass to this method the Graphics object of GDI+. As you can see, each line is rounded with the properties StartCap and EndCap of the Pen object.

C#
private void DrawLine(Graphics _objGraphics, PointF _objPointOne, 
                      PointF _objPointTwo, 
                      Color _objColor, int _intLineThickness)
{
      using(Pen objPen = new Pen(new SolidBrush(_objColor), _intLineThickness))
      {
            objPen.StartCap = LineCap.Round;
            objPen.EndCap = LineCap.Round;
            _objGraphics.DrawLine(objPen, _objPointOne, _objPointTwo);
      }
}

How to use this component?

This component is quite easy to use. Once added to your toolbox, drag it to your form, and you are in business! Now, all you have to do is to play with the properties which change the look of the circle. Those are under the category "LoadingCircle" in the Properties panel. Also, you can change the Active property to true or false to see the animation running or not.

The component has the following properties.

  • Color - The color of an inactive spoke.
  • OuterCircleRadius - This property is the radius of the outer circle. The value of this property is supposed to be higher than the InnerCircleRadius value.
  • InnerCircleRadius - This property is the radius of the inner circle.
  • NumberSpoke - This property is the number of spokes.
  • Active - Defines if the component is animated or not. So, if tour treatment is in progress, this property should be set to true, otherwise false.
  • SpokeThickness - Thickness of the line in pixel.
  • RotationSpeed - Animation speed. Lower is the value, faster is the animation.

Conclusion

Finally, I wish you will find this component useful. I had fun writing it, and wish you will use it. Thanks for reading this article.

Revision history

  • June 17, 2006 : Initial release.
  • February 05, 2007 : Better color management (alpha blending)
  • February 10, 2007 : Presets defined in the control (MacOS X, Internet Explorer 7 and FireFox). A new control has been added: LoadingCircleToolStripMenuItem. This control is compatible with the StatusStrip! Supports transparency. Some minors bug corrections.

License

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


Written By
Web Developer
Canada Canada
Looking for an online tool which allows you to sort the content of your text file, remove duplicate lines as well as empty lines. Go take a look at my new website: https://sortlines.com

Comments and Discussions

 
GeneralMy vote of 5 Pin
pcs041425-Apr-12 3:26
pcs041425-Apr-12 3:26 
AnswerAngles of spokes are shifted anticlockwise - any ideas? Solved! Pin
GuyThiebaut25-Mar-12 9:17
professionalGuyThiebaut25-Mar-12 9:17 
GeneralMy vote of 5 Pin
GuyThiebaut25-Mar-12 6:17
professionalGuyThiebaut25-Mar-12 6:17 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey18-Feb-12 3:08
professionalManoj Kumar Choubey18-Feb-12 3:08 
QuestionDoes not support threading Pin
elhenawyk20062-Feb-12 6:08
elhenawyk20062-Feb-12 6:08 
AnswerRe: Does not support threading Pin
Martin Gagne18-Feb-12 11:23
Martin Gagne18-Feb-12 11:23 
GeneralRe: Does not support threading Pin
MichaelMelio27-Jan-16 4:48
MichaelMelio27-Jan-16 4:48 
GeneralRe: Does not support threading Pin
Member 1229716819-Mar-17 5:27
Member 1229716819-Mar-17 5:27 
I know this is an old thread, but I didn't see anybody ever answered your question here and someone may run across this question with the same problem and would be nice to have an answer:

No, actually quite the oposite. The LoadingCircle MUST run on the UI thread. Any windows control can only have its visual properties referenced from the UI thread. The proper way to handle this with this type of control is to do your lengthy processing work on a separate thread and invoke methods to start / stop the wait circle on the UI thread. Any subroutine can be started on a separate thread by using the System.Threading.Thread object. Do this so that your lengthy processing does not 'freeze' your application until your work is done. I use this method of background processing for all of my processes that take extra time to run. Here is a VB.Net Example of threading:
Imports System.Threading

Public Class frmMain
    Private Sub frmMain_Shown(sender As Object, e As EventArgs) Handles Me.Shown
        Dim TWork As Thread = New Thread(Sub() DoWork())
        TWork.Name = "LengthyWork"
        TWork.IsBackground = True
        TWork.Start()
    End Sub

    Private Sub DoWork()
        'At the beginning of the work, invoke the StartWaitCircle method that will turn on the spinning circle:
        Invoke(ThreadSafeStartWaitCircle)

        'lengthy Processing Here

        'At the end of the lengthy work, invoke the EndWaitCircle method that will turn off the spinning circle
        Invoke(ThreadSafeEndWaitCircle)
    End Sub

    Private Delegate Sub delStartWaitCircle()
    Private ThreadSafeStartWaitCircle As New delStartWaitCircle(AddressOf StartWaitCircle)
    Private Sub StartWaitCircle()
        pc_ProgressCircle.Visible = True
        pc_ProgressCircle.Active = True
    End Sub

    Private Delegate Sub delEndWaitCircle()
    Private ThreadSafeEndWaitCircle As New delEndWaitCircle(AddressOf EndWaitCircle)
    Private Sub EndWaitCircle()
        pc_ProgressCircle.Active = False
        pc_ProgressCircle.Visible = False
    End Sub
End Class

In addition, if your lengthy work needs to reference anything on the UI thread, pass those in as parameters. Also if you need to update a control on the form during this process as well, create a delegate and use the Invoke() method to call a method that will do the updating for you. You can also pass parameters to methods from the Invoke() method. For more information, I would suggest researching System.Threading.
Questionreally cool... Pin
Avrajit24-Nov-11 4:08
Avrajit24-Nov-11 4:08 
QuestionCompact Framework Pin
stijn.vandenbroucke9-Oct-11 3:36
stijn.vandenbroucke9-Oct-11 3:36 
QuestionLike !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Pin
raananv31-Aug-11 12:51
raananv31-Aug-11 12:51 
GeneralMy vote of 5 Pin
v# guy2-Sep-10 3:37
v# guy2-Sep-10 3:37 
GeneralVery Nice Pin
Khaniya7-Mar-10 21:48
professionalKhaniya7-Mar-10 21:48 
Generaljust an observation Pin
binarydude200131-Jan-10 15:59
binarydude200131-Jan-10 15:59 
Generalwell done Pin
prolingua.geo8-Nov-09 23:02
prolingua.geo8-Nov-09 23:02 
GeneralNice Work !!! Pin
RicardoPDV13-Aug-09 12:14
RicardoPDV13-Aug-09 12:14 
Questionmemory leak? Pin
val17127-Oct-08 16:30
val17127-Oct-08 16:30 
AnswerRe: memory leak? Pin
polishz311-Feb-14 1:04
polishz311-Feb-14 1:04 
GeneralPrinting animation Pin
UltraWhack8-May-08 3:51
UltraWhack8-May-08 3:51 
GeneralRe: Printing animation Pin
jm334-Jun-08 12:47
jm334-Jun-08 12:47 
GeneralRe: Printing animation Pin
UltraWhack13-Jun-08 5:06
UltraWhack13-Jun-08 5:06 
GeneralNot disposing all GDI+ resources: System.AccessViolationException Pin
bwaide22-Apr-08 19:52
bwaide22-Apr-08 19:52 
GeneralRe: Not disposing all GDI+ resources: System.AccessViolationException Pin
Martin Gagne23-Apr-08 3:42
Martin Gagne23-Apr-08 3:42 
GeneralRe: Not disposing all GDI+ resources: System.AccessViolationException Pin
Luc Pattyn27-Mar-10 21:18
sitebuilderLuc Pattyn27-Mar-10 21:18 
QuestionHow to put a Loading Circle in a datgridviewcolmun/cell ? Pin
platinum0730-Dec-07 23:08
platinum0730-Dec-07 23:08 

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.