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

不问归期 提交于 2019-11-27 01:12:26

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);
    }

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 :)

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!