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 ?

H H
  • 263,252
  • 30
  • 330
  • 514
Pedrum
  • 634
  • 3
  • 7
  • 16

4 Answers4

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);
    }
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 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. –  May 24 '11 at 14:52
  • 2
    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. – Hans Passant May 24 '11 at 15:28
  • I'm using this code but it throws that `Animation failed` exception, what could be wrong? – Vahid Nateghi Nov 11 '13 at 05:51
  • 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 is – swdev Mar 23 '14 at 23:12
  • 2
    this works for sliding out a panel but how to slide in a panel. – tariq Nov 09 '14 at 05:48
  • 1
    @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); – oMiD Jan 10 '16 at 13:53
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 :)

Marino Šimić
  • 7,318
  • 1
  • 31
  • 61
  • very nice,thank you but why you use `Try`-`Catch`? it is expensive isnt it? – Jonathan Applebaum Feb 12 '18 at 08:59
  • 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. – Marino Šimić Oct 16 '18 at 16:54
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.

Soroush Falahati
  • 2,196
  • 1
  • 27
  • 38
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.