How can I add moving effects to my controls in C#?
Asked Answered
I

4

16

I have a Panel In my C# form and I have a button. When I click on the Button the invisible Panel Shows. Instead of that I want the Panel to move in or slide in. For example when you click on a combobox the dropdown list doesnt just pop in. I want my Panel to appear like that. How can I do that ?

Isle answered 23/5, 2011 at 19:52 Comment(3)
are you using winforms of wpf?Engrave
I liked the jQuery answer but it was deleted.Laurentia
@Henk : maybe it is a winforms app made in C# that uses a Webbrowser control :PFda
A
54

Window animation is a built-in feature for Windows. Here's a class that uses it:

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public static class Util {
    public enum Effect { Roll, Slide, Center, Blend }

    public static void Animate(Control ctl, Effect effect, int msec, int angle) {
        int flags = effmap[(int)effect];
        if (ctl.Visible) { flags |= 0x10000; angle += 180; }
        else {
            if (ctl.TopLevelControl == ctl) flags |= 0x20000; 
            else if (effect == Effect.Blend) throw new ArgumentException();
        }
        flags |= dirmap[(angle % 360) / 45];
        bool ok = AnimateWindow(ctl.Handle, msec, flags);
        if (!ok) throw new Exception("Animation failed");
        ctl.Visible = !ctl.Visible;
    }

    private static int[] dirmap = { 1, 5, 4, 6, 2, 10, 8, 9 };
    private static int[] effmap = { 0, 0x40000, 0x10, 0x80000 };

    [DllImport("user32.dll")]
    private static extern bool AnimateWindow(IntPtr handle, int msec, int flags);
}

Sample usage:

    private void button2_Click(object sender, EventArgs e) {
        Util.Animate(button1, Util.Effect.Slide, 150, 180);
    }
Approver answered 23/5, 2011 at 22:18 Comment(6)
Does this only work on contained controls, Hans? I tried it on a login form, but it looks like it vanished and closed the form.Pill
I tested it on contained controls. It should work on toplevel forms as well, however it is going hide the form on the first call since you'd have called Show() to display it. Replacing Show() so it animates the opening of the form is tricky, ask a question about it separately.Approver
I'm using this code but it throws that Animation failed exception, what could be wrong?Vala
It really useful! Got to say, it will solve all of my animation needs. I got the animation failed exception when trying to do a blend animation style. Not sure though what kind of animation that isGoodloe
this works for sliding out a panel but how to slide in a panel.Habile
@tariq, You can do it by changing fourth parameter in calling Util.Animate method which is movement angle, such as: Util.Animate(button1, Util.Effect.Slide, 150, 360);Madcap
N
15

If you are using .NET 4 (if not replace Task with Thread), a function similar to this could be a start:

    private void slideToDestination(Control destination, Control control, int delay, Action onFinish)
    {
        new Task(() =>
        {
            int directionX = destination.Left > control.Left ? 1 : -1;
            int directionY = destination.Bottom > control.Top ? 1 : -1;

            while (control.Left != destination.Left || control.Top != destination.Bottom)
            {
                try
                {
                    if (control.Left != destination.Left)
                    {
                        this.Invoke((Action)delegate()
                        {
                            control.Left += directionX;
                        });
                    }
                    if (control.Top != destination.Bottom)
                    {
                        this.Invoke((Action)delegate()
                        {
                            control.Top += directionY;
                        });
                    }
                    Thread.Sleep(delay);
                }
                catch
                {
                    // form could be disposed
                    break;
                }
            }

            if (onFinish != null) onFinish();

        }).Start();
    }

Usage:

slideToDestination(sender as Control, panel1, 10, () => MessageBox.Show("Done!"));
slideToDestination(sender as Control, panel1, 0, null);

As action you would send some boolean variable to set to true so that you know that the animation has finished or some code to run after it. Beware of deadlocks when calling with a null action. You could run two animations on the same control in two different directions with the same speed, and it will stay where it was forever and of course two animations simultaneusly can make the control go infinitely in some direction because the while will never finish :)

Nightmare answered 23/5, 2011 at 20:28 Comment(2)
very nice,thank you but why you use Try-Catch? it is expensive isnt it?Teryn
it is here to prevent an exception when closing the form since you cannot animate on a disposed form. this could be solved in a more complicated way by using the form Closing event and having tasks that are cancellable and doing some other if statements around each move but it would probably be even slower.Fda
T
4

Check out the library I wrote last year:

WinForm Animation Library [.Net3.5+]

A simple library for animating controls/values in .Net WinForm (.Net 3.5 and later). Key frame (Path) based and fully customizable.

https://falahati.github.io/WinFormAnimation/

new Animator2D(
        new Path2D(new Float2D(-100, -100), c_control.Location.ToFloat2D(), 500))
    .Play(c_control, Animator2D.KnownProperties.Location);

This moves the c_control control from -100, -100 to the location it was in first place in 500 ms.

Tver answered 19/5, 2016 at 15:43 Comment(0)
P
1

For WinForms, you could start with the Panel location being off screen.

Employ a Timer, and in the Tick event, shift the Panel's location slowly into view until it is at your predefined coordinates.

Lots of ways to skin a cat, but this is how I'd do it.

Pill answered 23/5, 2011 at 20:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.