Animação simples em WinForms
Pergunta
Imagine que você deseja animar algum objeto em um WinForm.Você configura um cronômetro para atualizar o estado ou modelo e substitui o evento de pintura do Formulário.Mas a partir daí, qual é a melhor maneira de repintar continuamente o Formulário da animação?
- Invalidar o Formulário assim que terminar de desenhar?
- Configurar um segundo cronômetro e invalidar o formulário em intervalos regulares?
- Talvez haja um padrão comum para isso?
- Existem classes .NET úteis 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 SO?
Solução
Em algumas situações, é mais rápido e conveniente não desenhar usando o evento paint, mas pegar o objeto Graphics do controle/formulário e pintar "sobre" ele.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 como:
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 mesmo uso isso em alguns controles e tenho imagens armazenadas em buffer para "limpar" o fundo, quando o objeto de interesse se move ou precisa ser removido.
Outras dicas
Eu criei uma biblioteca que pode ajudar com isso.Chama-se Transições e pode ser encontrado aqui: http://code.google.com/p/dot-net-transitions/
Ele usa temporizadores executados em um thread de segundo plano para animar os objetos.A biblioteca é de código aberto, então se for útil para você, você pode olhar o código para ver o que ele está fazendo.
O que você está fazendo é a única solução que já usei no WinForms (um timer com redesenhos constantes).Existem várias técnicas que você pode usar para tornar a experiência do usuário mais suave (como buffer duplo).
Você pode querer experimentar o WPF.Existem recursos integrados para fazer animações no WPF e são muito mais suaves (e exigem menos código e nenhuma sincronização de sua parte) do que uma solução baseada em temporizador.
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):