WinForms Animation

[This post stemmed from a conversation I had today where I was trying to preach the wonders of WPF – particularly in terms of being able to declare simple yet effective animations for UI elements. Contrasting it to what we used to have to do “when I was a lad”…]


A couple of months back when I was working on the WinForms version on my PhotoPlay applet I was trying to do some simple animation using WinForms (GDI+). The effect I was trying to generate was a “fade away”. When a selected photo was removed (via Delete key) it was to fade to transparent and also shrink to nothingness around its centre.


I wanted to use a Timer to make sure that the effect always took a set amount of time, e.g. 500ms. I always use this approach because it makes sure your animations behave nicely no matter how meagre your hardware. The only other obvious approach is to animate every frame – regardless of how long in takes – I’ve never found this too useful.


So with my “fade away” animation coded up in the form I realised that I now how the need for another animation. This time when double-clicking on an image it needed to scale to full size, rotate to zero degrees and position itself in the centre of the window. Hmm… another Timer and custom code perhaps. At the same time I realised my previous “fade away” animation wasn’t working to well when a user tried multiple deletes – deleting one before the previous had fully faded.


Obviously creating a separate Timer instance for every animatable object isn’t going to be very efficient in terms of costly timer resources. Hence the birth of the Transition and TransitionManager classes.


Spencen.Drawing


This class allows simple animations to be performed with very minimal code in a WinForms application. The TransitionManager internally uses a BackgroundWorker to perform the animation – bubbling an event up whenever a transition step occurs so that the UI can redraw. The thing to note with all of this is that it will only work with classes that derive from GraphicsObject. Within PhotoPlay this is the individual photos – but it can be any regular or irregular shaped graphic.


Typically the UI will consist of a number of graphical elements that require GDI+ rendering and hence these could be stored in a “shapes” collection and rendered in OnPaint.

        protected override void OnPaint(PaintEventArgs e)        {            base.OnPaint(e);            foreach (GraphicsObject graphicsObject in shapes)            {                graphicsObject.Paint(e.Graphics);            }        }

To animate these objects its as simple as something like the following (although you may prefer slightly less randomness in your own applications ).

        private void animateButton_Click(object sender, EventArgs e)        {            Random randomizer = new Random();            foreach (GraphicsObject graphicsObject in shapes)            {                Transition transition = new Transition(graphicsObject,                    randomizer.Next(1000) + 200,                    randomizer.Next(360),                    randomizer.Next(5) + 1,                    new PointF(randomizer.Next(400) + 50, randomizer.Next(400) + 50),                    randomizer.Next(50) / 100.0f + 0.5f);                transitionManager.Add(transition);            }            transitionManager.Start();        }        private void transitionManager_TransitionStep(object sender, TransitonStepEventArgs e)        {            // A transition has occurred so force a redraw. Would be better if we added            // Bounds to GraphicsObject so we could do Invalidate(e.Transition.Target.Bounds);            Invalidate();        }

Here’s a ClickOnce online sample and here’s the zipped source code for it.


Windows Forms Transition Manager Screenshot


Roll on WPF and Storyboard double buffer animations


[UPDATE: For those looking for a more fully featured transition/animation library for WinForms I suggest you take a look at Richard’s offering up at http://code.google.com/p/dot-net-transitions. ]

4 thoughts on “WinForms Animation”

  1. You’re welcome Julia!

    I did do some further updates to this to help address some minor issues – mainly to do with interrupting animations part way through, thread locking, and to allow for repeating (continuous) animations.

    I also have some code somewhere to do hit testing on the objects. This is useful in the scenario where you want to allow the user to interact with the GraphicsObjects. It’s actually messy because you have to manually perfrom the calculations done by the transforms to turn a mouse position into a position relative to each GraphicsObject. Still it only needs to be done once – that’s how I did the hit-testing for the photos in my PhotoPlay applet.

    If you have a need – let me know and I’ll post a follow-up entry covering those updates.

    Cheers, Nigel

  2. I want to write a blackjack game and animate the cards – it seems like I would need the code you are describing. Please do post it. I’m learning C# after 10 years of Java and I am amazed how much easier everything is than with Java Swing.

  3. I just want to know that the animation field has any future or not. I am an Indian and here’s IT industry is booming, will it beneficial to make our career in animation. I would like you efforts too in writing this articles.
    Thanks !

Comments are closed.