Animazione semplice in WinForms
Domanda
Immagina di voler animare qualche oggetto su un WinForm.Imposti un timer per aggiornare lo stato o il modello e sovrascrivere l'evento paint del modulo.Ma da lì, qual è il modo migliore per ridipingere continuamente il modulo per l'animazione?
- Invalidare il modulo non appena hai finito di disegnare?
- Impostare un secondo timer e invalidare il modulo a intervalli regolari?
- Forse esiste uno schema comune per questa cosa?
- Esistono classi .NET utili per dare una mano?
Ogni volta che devo farlo scopro un nuovo metodo con un nuovo inconveniente.Quali sono le esperienze e le raccomandazioni della comunità SO?
Soluzione
In alcune situazioni, è più veloce e più conveniente non disegnare utilizzando l'evento paint, ma ottenere l'oggetto Graphics dal controllo/form e dipingere "su" di esso.Ciò potrebbe causare alcuni problemi con opacità/anti aliasing/testo ecc., ma potrebbe valerne la pena in termini di non dover ridipingere l'intero shabang.Qualcosa sulla falsariga di:
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++]));
}
Lo uso personalmente in alcuni controlli e ho immagini memorizzate nel buffer per "cancellare" lo sfondo quando l'oggetto di interesse si sposta o deve essere rimosso.
Altri suggerimenti
Ho creato una libreria che potrebbe aiutare in questo.Si chiama Transizioni e può essere trovato qui: http://code.google.com/p/dot-net-transitions/
Utilizza timer in esecuzione su un thread in background per animare gli oggetti.La libreria è open source, quindi se ti è utile, puoi guardare il codice per vedere cosa sta facendo.
Quello che stai facendo è l'unica soluzione che abbia mai usato in WinForms (un timer con ridisegni costanti).Esistono numerose tecniche che è possibile utilizzare per rendere più fluida l'esperienza dell'utente (come il doppio buffering).
Potresti provare WPF.Esistono funzionalità integrate per eseguire animazioni in WPF e sono molto più fluide (e richiedono meno codice e nessuna sincronizzazione da parte tua) rispetto a una soluzione basata su timer.
Tieni presente che non è necessario utilizzare WPF nell'intera app per tale soluzione;è possibile comprimere questa funzionalità in un controllo WPF e incorporare il controllo in un'applicazione WinForms (o in un'app non gestita, del resto):