The idea for this component came to me while viewing the Iconits article[^]. The idea was really good, and while hovering over the icons from left to right, an idea came to me that this could make a great progress bar. Also, I missed some functionality and customizations, and because I already have a fully working component for animations (Animating Windows Forms[^]), I decided to build my own component.
To fully understand the code, you will need knowledge about Windows Forms,
Timers, designer support, and much more. I will not describe everything in detail. Have a look at the References for articles describing parts of my implementations in detail. On my way to the final progress bar control, I implemented several helping controls built on top of each other, which helped me to separate the whole big problem into smaller pieces. Doing so should be in the back of the head of every developer. It not only helps to keep classes small, and thus not to lose overview, but in this case, it also led to some controls which can also be used separately outside of the actual progress bar.
Usage is very straightforward. There is a total of four controls which can all be used by just dragging them onto a
Form with the designer. Nearly everything can be customized by using the designer, so just start exploring.
I have put much effort in supplying good samples in the downloads. They cover most of the functionality of this component, so if you want to know what the different controls are capable of, then play around with them. The downloads are primarily so big because of the images contained in the samples. The component itself is rather small.
As already stated, I will not go into the details here, but will just describe how the classes are related to each other. Everything is well documented, and a help file is also included as a programmer's reference.
This control is somehow similar to the
PictureBox class. At least, both have the common functionality of showing an
Image. It has properties for applying alpha, rotation, gradient back colors, and some more. Furthermore, it has a property
BaseSizeMode which handles, together with the
Zoom property, how the shown
Image is resized. Finally, it has the capability to show a second
Image without alpha blending and resizing, with customizable rotation and alignment.
Some of those properties can not only be accessed or set separately, but also modified with the
State property. This one doesn't have a real benefit within this control but contains all the properties which will get animated in later stages.
Its functionality is demonstrated in the top left sample of the main form in the sample application.
This class is derived from the
ExtendedPictureBox. It uses my animation component, and thus for every animated property, I have implemented an animator class and an animator which bind them all together (everything can be found in the
Animators sub namespace). The main extension is the
Animate function which gets a new
State object. Calling it will result in a smooth animation from the current to the new
State. Furthermore, it has several properties, functions, and events to control the animation.
This one is actually not required for the progress bar but I nevertheless implemented it. It derives from
AnimatedPictureBox and now holds two
EndState. The first one will be displayed when the mouse cursor is not located over the control. When the mouse enters the control, it will animate its state into the second one.
The bottom left sample shows this one. Don't forget to click the button at the bottom right of the upcoming form which has some more predefined samples. Also notice that the sample selector is built with this control.
Finally, we are coming to the actual aim of this component. The
AnimatedPicturesProgressBar has a
Steps property where
ProgressSteps describing the visual appearance of every step of the progress bar can be added. For every step, an
AnimatedPictureBox is created and placed horizontally one after the other in the control. You can define a total of three states representing steps which are not yet started, in progress, or finished. Furthermore, you can define if and how the current step gets a little extra animation, and some more properties influencing the animations. After adding all the steps and setting all the properties, a call to
EndInit is required (the designer will do this for you if you configure the progress bar completely with it), and if it's the second run, also to
Reset. Then, for each starting step, a call to
NextStep will advance the progress by one step. It is important to understand that if the main thread is blocked with some heavy operation, the animation won't show up (like any other repainting in the GUI). There are several ways to avoid this:
- Do the processing in a separate thread. Don't forget to use
Invoke to delegate the call to
NextStep over the thread boundaries. This is the best way to keep the animations smooth without any heavy performance penalty.
- Set the
true. This way, the call to
NextStep will return after the transition is completed. The performance might reduce a bit because your processing will be stopped while the animation is going on, and the rotation of the little extra image and the back color transition while a step is being processed won't be visible.
- Ensure by yourself the control is being repainted. This can be done either by calling
Application.DoEvents. Keep in mind that calling these too often might result in a severe performance penalty, and calling them not often enough will result in a not very smooth or slowed down animation. Thus, I recommend using one of the other two solutions above.
Have a look at the bottom right sample. It shows all the combinations possible.
Just a small note on the memory consumption before everyone starts complaining that the component is allocating too much memory: This is totally normal! As you can imagine, much drawing logic is needed in this component. I also create in-memory bitmaps to ease this. Surely, this encourages the CLR to allocate much memory but it will also release it at regular intervals. Sure, I could force the garbage collector to do its work and dispose explicitly more often, but this is something not necessary in a managed environment and it could even reduce performance.
Several articles helped me with the implementations details. The most important ones are:
- Some performance tweaking here and there should still be possible (although I did my best to make it fast).
- I'm eager to extend this component with useful features requested here. So, if anyone has further suggestions, please feel free to post them here.
- May 13th, 2006 - Version 1.0.0
- July 1st, 2006 - Version 1.1.0
- July 15th, 2006 - Version 1.2.0
- Added support to display text in all four controls. The animated controls can animate the size, rotation, halo width, halo color, and fore color. This feature also supports the alignment of the text. Have a look at the samples - this adds some really cool effects.
- Because of this, some constructors have changed and will probably confuse the designer. This should only hurt if you have defined steps for the
AnimatedProgressBar within the designer. Please correct those errors by hand.
ForeColor changed the color of the border in version 1.1.0. Now it changes the color of the text. The color of the border can now be adjusted by the new property
- Changed the
Editor of all my properties of type
Color, which allows to set alpha values on the colors within the editor. Look here[^] for details regarding this.
- November 18th, 2006 - Version 1.3.0
- Added shadow effect for the images.
- Added a total of three offset properties which enhances visualization and animation effects.
AnimatedPictureButton reacts on mouse clicks to give the user a visual feedback that he hit the button.
- Several other minor changes and fixes.
- Changed the samples to reflect those changes. Because the sample forms where getting too big, I replaced the normal
TrackBar with the one from NicolNghia which is smaller. You can find the control in his article: Advanced TrackBar (Slider) Control with MAC Style (C# and VB.NET)[^].