Animation-Klasse

Die Animation-Klasse von beta.unclassified.de zeigt ein Anwendungsszenario f?r die in einem fr?heren Eintrag angesprochene DelayedCall Klasse. Mit ihr können Controls als auch Forms animiert werden, ohne das ständige Neuzeichnen bei Resize-Operationen im Hintergrund hervorzurufen.

Beispiel:
Ein Form wird in seiner Größe geändert. Im ResizeEnd-Event wird die gew?nschte Animation der beinhaltenden Controls aufgerufen.
Die Controls werden ?ber die Animation-Klasse und der DelayedCall auf die jeweils ?bergebenen Größenänderungen angepasst, so daß eine sanfte Animation erfolgt.

Ein Beispiel sei hier kurz vermerkt, wie die Animation-Klasse angewendet werden kann. ucT ist in diesem Fall ein Control (in meiner Testapplikation ein UserControl mit einigen eingebetteten Controls, wie Buttons, Textbox usw). F?r die vertikale Animation wird der Animation-Klasse den Parametern ResizeVert, dem Control (welches animiert werden soll), die letztendliche zu erreichende Höhe, eine Methode die nach Abschluß aufgerufen werden soll und die Dauer der Animation, aufgerufen.

[source:csharp] private void TestForm_ResizeEnd(object sender, EventArgs e)
{
new KeenTech.UI.Animation(KeenTech.UI.AnimationTypes.ResizeVert, this.ucT,
this.ClientSize.Height – ucT.Height, new KeenTech.UI.AnimationFinishedHandler(Test), 350);
new KeenTech.UI.Animation(KeenTech.UI.AnimationTypes.ResizeHoriz, this.ucT,
this.ClientSize.Width – ucT.Width, new KeenTech.UI.AnimationFinishedHandler(Test), 350);
}
[/source]

Die Animation-Klasse sieht wie folgt aus (Namespace wurde an eigene Begebenheiten angepasst):

[source:csharp] using System;
using System.Windows.Forms;
using System.Drawing;

// Benötigt die Klasse DelayedCall
//
// Anwendung:
//
// Ausblenden und anschließendes Schließen des Fensters:
// (Close ist Methode des Fensters this)
//
// new Animation(AnimationTypes.FadeOut, this, 0, Close);
//
// Sanftes Ändern der Höhe des Fensters auf 500 Pixel:
// (SomeTaskWhenResized ist die aufzurufende Funktion nach Abschluss der Größenänderung)
//
// new Animation(AnimationTypes.ResizeVert, this, 500 – Height, SomeTaskWhenResized);
//
// .NET-Kompatibilität: 2.0
//
// Hinweise f?r .NET 1.1: Als EventHandler muss ein ’new delegate…‘ ?bergeben werden,
// der Funktionsname allein ist eine Abk?rzung, die seit .NET 2.0 möglich ist.

namespace KeenTech.UI
{
public enum AnimationTypes
{
None,
ResizeHoriz,
ResizeVert,
FadeIn,
FadeOut
}

public delegate void AnimationFinishedHandler();

public class Animation
{
AnimationTypes type;
object target;
int offset;
AnimationFinishedHandler handler;
int start;
int end;
int interval;
int duration;
int timePassed;
bool cancellationPending = false;

public Animation(AnimationTypes type, object target, int offset, AnimationFinishedHandler handler)
: this(type, target, offset, handler, 0)
{
}

public Animation(AnimationTypes type, object target, int offset, AnimationFinishedHandler handler, int duration)
{
this.type = type;
this.target = target;
this.offset = offset;
this.handler = handler;
this.duration = duration;

// timings in ms
interval = 10;
timePassed = 0;

Control c;
Form f;
switch (type)
{
case AnimationTypes.ResizeHoriz:
c = target as Control;
if (c == null)
return;
start = c.Width;
end = start + offset;
if (this.duration == 0)
this.duration = 150;
break;
case AnimationTypes.ResizeVert:
c = target as Control;
if (c == null)
return;
start = c.Height;
end = start + offset;
if (this.duration == 0)
this.duration = 150;
break;
case AnimationTypes.FadeIn:
f = target as Form;
if (f == null)
return;
start = (int)(f.Opacity * 100);
end = start + offset;
if (this.duration == 0)
this.duration = 250;
break;
case AnimationTypes.FadeOut:
f = target as Form;
if (f == null)
return;
start = (int)(f.Opacity * 100);
end = start + offset;
if (this.duration == 0)
this.duration = 2000;
break;
default:
return;
}

Next();
}

public void Cancel()
{
cancellationPending = true;
}

private double MakeCurve()
{
double timePercent = (double)timePassed / (double)duration;

// we use the sine function from 3pi/2 to 5pi/2
// scale down linear time percentage from 0…1 to 3pi/2 to 5pi/2
double curve = Math.Sin(1.5 * Math.PI + timePercent * Math.PI);
// translate sine output from -1…1 to 0…1
curve = (curve + 1) / 2;
// DEBUG: don’t use curve but linear progress instead
//curve = timePercent;

return curve;
}

public void Next()
{
if (cancellationPending)
return; // and don’t come back

timePassed += interval;
if (timePassed > duration)
{
if (handler != null)
handler();
return;
}

Control c;
Form f;
Rectangle wa;
switch (type)
{
case AnimationTypes.ResizeVert:
c = target as Control;
c.Height = start + (int)((end – start) * MakeCurve());
wa = Screen.FromControl(c).WorkingArea;
if (c is Form && c.Bottom > wa.Bottom)
{
c.Top -= c.Bottom – wa.Bottom;
if (c.Top < wa.Top)
{
c.Top = wa.Top;
}
}
break;
case AnimationTypes.ResizeHoriz:
c = target as Control;
c.Width = start + (int)((end – start) * MakeCurve());
wa = Screen.FromControl(c).WorkingArea;
if (c is Form && c.Right > wa.Right)
{
c.Left -= c.Right – wa.Right;
if (c.Left < wa.Left)
{
c.Left = wa.Left;
}
}
break;
case AnimationTypes.FadeIn:
f = target as Form;
f.Opacity = (double)(start + ((end – start) * MakeCurve())) / 100;
break;
case AnimationTypes.FadeOut:
f = target as Form;
f.Opacity = (double)(start + ((end – start) * MakeCurve())) / 100;
break;
}

new DelayedCall(new DelayedCall.Function(this.Next), interval);
}
}
}

[/source]

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.