Animação simples no WinForms

Imagine que você deseja animar algum object em um WinForm. Você configura um cronômetro para atualizar o estado ou modelo e anula o evento de pintura do formulário. Mas a partir daí, qual é a melhor maneira de repintar continuamente o formulário para a animação?

  • Invalidar o formulário assim que terminar de desenhar?
  • Configurar um segundo timer e invalidar o formulário em um intervalo regular?
  • Talvez haja um padrão comum para isso?
  • Existe alguma class .NET útil para ajudar?

Cada vez que preciso fazer isso, descubro um novo método com uma nova desvantagem. Quais são as experiências e recomendações da comunidade de SO?

Em algumas situações, é mais rápido e mais conveniente não desenhar usando o evento paint, mas obtendo o object Graphics do controle / formulário e pintando “on”. Isso pode causar alguns problemas com opacidade / anti-aliasing / texto etc, mas pode valer a pena em termos de não ter que repintar todo o shabang. Algo ao longo das linhas de:

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++])); } 

Eu uso isso em alguns controles e tenho imagens em buffer para “limpar” o fundo com, quando o object de interesse se move ou precisa ser removido.

Eu criei uma biblioteca que pode ajudar com isso. É chamado de Transições e pode ser encontrado aqui: http://code.google.com/p/dot-net-transitions/

Ele usa timers em execução em um thread de segundo plano para animar os objects. A biblioteca é de código aberto, portanto, se for de alguma utilidade para você, você pode ver o código para ver o que está fazendo.

O que você está fazendo é a única solução que já usei no WinForms (um timer com redesenho constante). Há um monte de técnicas que você pode usar para tornar a experiência do usuário mais suave (como double-buffering).

Você pode querer experimentar o WPF. Existem resources internos para fazer animações no WPF, e eles são muito mais suaves (e requerem menos código e nenhuma synchronization de sua parte) do que uma solução baseada em timer.

Observe que você não precisa usar o WPF em todo o aplicativo para essa solução; é possível empacotar essa funcionalidade em um controle WPF e incorporar o controle em um aplicativo WinForms (ou em um aplicativo não gerenciado):

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