Simple animation in WinForms

2019-01-13 18:35发布

问题:

Imagine you want to animate some object on a WinForm. You setup a timer to update the state or model, and override the paint event of the Form. But from there, what's the best way to continually repaint the Form for the animation?

  • Invalidate the Form as soon as you are done drawing?
  • Setup a second timer and invalidate the form on a regular interval?
  • Perhaps there is a common pattern for this thing?
  • Are there any useful .NET classes to help out?

Each time I need to do this I discover a new method with a new drawback. What are the experiences and recommendations from the SO community?

回答1:

In some situations, it's faster and more convenient to not draw using the paint event, but getting the Graphics object from the control/form and painting "on" that. This may give some troubles with opacity/anti aliasing/text etc, but could be worth the trouble in terms of not having to repaint the whole shabang. Something along the lines of:

private void AnimationTimer_Tick(object sender, EventArgs args)
{
    // First paint background, like Clear(Control.Background), or by
    // painting an image you have previously buffered that was the background.
    animationControl.CreateGraphics().DrawImage(0, 0, animationImages[animationTick++])); 
}

I use this in some Controls myself, and have buffered images to "clear" the background with, when the object of interest moves or need to be removed.



回答2:

I've created a library that might help with this. It's called Transitions, and can be found here: http://code.google.com/p/dot-net-transitions/

It uses timers running on a background thread to animate the objects. The library is open-source, so if it is any use to you, you can look at the code to see what it's doing.



回答3:

What you're doing is the only solution I've ever used in WinForms (a timer with constant redrawings). There are a bunch of techniques that you can use to make the user's experience with it smoother (such as double-buffering).

You might want to give WPF a try. There are built-in facilities for doing animations in WPF, and they're much smoother (and require less code and no synchronization on your part) than a timer-based solution.

Note that you do not need to use WPF throughout your whole app for that solution; it's possible to pack this functionality into a WPF control and embed the control in a WinForms application (or an unmanaged app, for that matter):

http://www.codeproject.com/KB/WPF/WPF_UserControls.aspx