Perform Windows Forms property animation in C#

[property animation]

Making a control’s properties change over time is called property animation. Keeping track of where a control’s properties, for example its position as it moves, can be tricky, particularly if you need to animate multiple objects at the same time. This example uses the following ControlSprite class to keep track of a control while it moves in a straight line.

// Information about a move in progress.
public class ControlSprite
{
    public System.Windows.Forms.Control MovingControl;
    public int EndX, EndY;
    public float CurrentX, CurrentY;

    private float Dx, Dy;
    private DateTime LastMoveTime;
    private TimeSpan TotalElapsed, MoveUntil;
    private Timer MoveTimer;

    public delegate void DoneEventHandler(object sender);
    public event DoneEventHandler Done;

    // Prepare to move the control.
    public ControlSprite(System.Windows.Forms.Control control)
    {
        MovingControl = control;
    }

    // Start moving.
    public void Start(int end_x, int end_y, int pixels_per_second)
    {
        CurrentX = MovingControl.Location.X;
        CurrentY = MovingControl.Location.Y;
        EndX = end_x;
        EndY = end_y;
        
        // Calculate the total distance.
        float dx = EndX - CurrentX;
        float dy = EndY - CurrentY;
        float dist = (float)Math.Sqrt(dx * dx + dy * dy);

        // Calculate the X and Y amounts to move per second.
        Dx = pixels_per_second * dx / dist;
        Dy = pixels_per_second * dy / dist;

        // See how long the total move will take.
        int milliseconds = (int)(1000.0f * dist / pixels_per_second);
        MoveUntil = new TimeSpan(0, 0, 0, 0, milliseconds);
        TotalElapsed = new TimeSpan(0);

        // Make the timer.
        MoveTimer = new Timer();
        MoveTimer.Interval = 10;
        MoveTimer.Tick += MoveTimer_Tick;

        // Start moving.
        Start();
    }

    // Resume moving.
    public void Start()
    {
        LastMoveTime = DateTime.Now;
        MoveTimer.Enabled = true;
    }

    // Stop moving.
    public void Stop()
    {
        MoveTimer.Enabled = false;
    }

    // Move the control.
    private void MoveTimer_Tick(object sender, EventArgs e)
    {
        // See how long it's been since the last move.
        DateTime now = DateTime.Now;
        TimeSpan elapsed_since_last = now - LastMoveTime;
        LastMoveTime = DateTime.Now;

        // See if we should stop.
        TotalElapsed += elapsed_since_last;
        if (TotalElapsed >= MoveUntil)
        {
            // Stop.
            MoveTimer.Enabled = false;
            CurrentX = EndX;
            CurrentY = EndY;
            if (Done != null) Done(this);
        }
        else
        {
            // Continue.
            CurrentX +=
                (float)(Dx * elapsed_since_last.TotalSeconds);
            CurrentY +=
                (float)(Dy * elapsed_since_last.TotalSeconds);
        }

        // Move the control to its new location.
        MovingControl.Location =
            new Point((int)CurrentX, (int)CurrentY);
    }
}

The class starts with some relatively straightforward declarations. The only really interesting part here is the declaration of the Done event, which the class raises when its control has finished moving.

The class’s constructor takes as a parameter the control that it will move.

The first overloaded version of the Start method gets things moving. It saves the control’s current and end locations, and calculates the total distance the control must travel. It then uses that distance and the pixels_per_second parameter to determine how much it must increment the control’s X and Y coordinate per second to achieve the desired movement in pixels per second. The Start method calculates the total amount of time the movement will take, creates a Timer to control the movement, and then calls the second overloaded version of Start.

The second version of Start saves the current time in the LastMoveTime variable and enables the Timer.

The Stop method simply disables the sprite’s Timer.

When the Timer raises its Tick event, the sprite determines how long it’s been since the last time it updated the control’s position and adds the elapsed time to the total elapsed time so far. If the control has been moving for long enough to reach its destination, the code disables the Timer, moves the control to its final position, and raises the Done event. If the control has not been moving long enough to reach its destination, the code increments the control’s X and Y coordinates.

The example program uses two sprites to animate a Button and a Label moving at the same time.

The following code shows how the program prepares to animate its controls.

private ControlSprite ButtonSprite, LabelSprite;

// Make the control sprites.
private void Form1_Load(object sender, EventArgs e)
{
    ButtonSprite = new ControlSprite(btnStart);
    ButtonSprite.Done += ButtonSprite_Done;
    LabelSprite = new ControlSprite(lblMessage);
}

This code declares two ControlSprite objects. The Load event handler initializes the objects and sets the Button‘s Done event handler (described shortly).

When you click the Button, the following code executes.

// Start or stop.
private void btnStart_Click(object sender, EventArgs e)
{
    const int PixelsPerSecond = 200;

    if (btnStart.Text == "Start")
    {
        // Start button. Change the caption to Stop.
        btnStart.Text = "Stop";

        // See where we are.
        if (btnStart.Location.X == 12)
        {
            // Move the button down and right.
            ButtonSprite.Start(197, 229, PixelsPerSecond);
            LabelSprite.Start(12, 232, PixelsPerSecond);
        }
        else if (btnStart.Location.X == 197)
        {
            // Move the button up and left.
            ButtonSprite.Start(12, 12, PixelsPerSecond);
            LabelSprite.Start(186, 12, PixelsPerSecond);
        }
        else
        {
            // Continue the button's previous move.
            ButtonSprite.Start();
            LabelSprite.Start();
        }
    }
    else
    {
        // Stop button. Change the caption to Start.
        btnStart.Text = "Start";

        // Stop moving.
        ButtonSprite.Stop();
        LabelSprite.Stop();
    }
}

This code first determines whether the Button currently says Start or Stop. If the Button says Start, the code makes it say Stop. Then if the Button‘s X position is 12, the code starts both sprites, moving the controls to positions (197, 229) and (12, 232). If the Button‘s X position is 197, the code starts both sprites, moving the controls to positions (12, 12) and (186, 12).

If the Button‘s X position is neither 12 nor 197, the code simply calls the sprites’ Start methods so they continue the previous move. (That way you can stop and restart the movement whenever you like.)

If the Button starts with caption Stop, then the code simply calls the sprites’ Stop methods.

The following code shows the Button‘s Done event handler.

// The button is done moving.
public void ButtonSprite_Done(object sender)
{
    btnStart.Text = "Start";
}

This code simply resets the Button‘s text to Start so you can restart the animation.

You can use similar techniques to do other kinds of property animation, although defining some animations may contain extra work. For example, you would need to figure out how to change a color to make it gradually change from red to green.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in algorithms, classes, multimedia and tagged , , , , , , , , , , , , . Bookmark the permalink.

4 Responses to Perform Windows Forms property animation in C#

  1. danie says:

    Written up well. very informative. Thanks

  2. danie says:

    control the motion of a circle on the form using arrow keys in C#
    Check it here :
    http://kodingexamples.blogspot.com/2014/07/how-to-control-objectsprites-motion.html

  3. chromehit says:

    request list :

    web spider
    youtube downloader
    blogspot post
    image upload amazon, etc
    face recognition
    video process effects
    anticrack and licence system online
    remote control pc and webcam

    • RodStephens says:

      That’s a pretty good list! Unfortunately I think most of those would be developed at a lower level than I at least can reasonably handle in C#.

      web spider

      You can build a web spider by using the WebBrowser control. See this example for some tips to get you started:

      Unfortunately WebBrowser is pretty heavy so this will be relatively slow. A faster approach would be to download files directly and parse them yourself. (See Download files from the web in C#.) Unfortunately that will require you to parse the files.

      You can download files and then load them into the DOM, but even that’s going to be somewhat slow. Basically I think you can build a spider that visits a site and even possibly checks its outbound links, but I don’t know if you can build something effective to crawl over a big part of the web. (And you should obey the settings fro the sites you visit.)

      youtube downloader

      If you can figure out the URL where a video is kept, you may be able to download it using this technique:

      . But they’re FLV files so you would need something to play them.

      image upload amazon, etc

      I’m not sure what you mean by this one. Amazon won’t let you upload files to its severs.

      But you can use the example Upload files to an FTP server in C# to upload files if you have permission on the server.

      face recognition

      I’m sure this can be done, but it’s way beyond anything I can do.

      video process effects

      This probably wouldn’t be too bad if you had access to the frame data, but I haven’t found a good way to get at it. You may be able to buy a toolkit to do this, but the basic tools Microsoft provides (see Microsoft Expression Encoder) don’t let you work with the data at this level.

      anticrack and licence system online

      There’s this example: Register a program for a particular system in C#. It provides some basic ideas that I think would be pretty secure if you use the crypto library. There are a few examples on this site that use that library.

      remote control pc and webcam

      I don’t know how to approach this one either. There are probably libraries out there that let you work with a remote webcam, but I haven’t used them and I suspect remote PC control may require working at a lower level than is easy.

      You could certainly install a watcher process (possibly a web service) on the remote PC and have it communicate with your PC over the network. For example, you could then tell it to do things on the remote computer.


      If anyone else has ideas, I’d love to see them.

Leave a Reply

Your email address will not be published. Required fields are marked *