Как добавить движущиеся эффекты к элементам управления на C #?

У меня есть панель в моей форме C #, и у меня есть кнопка. Когда я нажимаю кнопку, отображается невидимая панель. Вместо этого я хочу, чтобы панель двигалась внутрь или выдвигалась. Например, когда вы нажимаете на поле со списком, раскрывающийся список не появляется просто так. Я хочу, чтобы моя панель выглядела вот так. Как я могу это сделать ?


person Pedrum    schedule 23.05.2011    source источник
comment
вы используете Winforms из WPF?   -  person jimjim    schedule 23.05.2011
comment
Мне понравился ответ jQuery, но он был удален.   -  person Henk Holterman    schedule 23.05.2011
comment
@Henk: возможно, это приложение winforms, созданное на C #, которое использует элемент управления Webbrowser: P   -  person Marino Šimić    schedule 24.05.2011


Ответы (4)


Оконная анимация - это встроенная функция Windows. Вот класс, который его использует:

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

Пример использования:

    private void button2_Click(object sender, EventArgs e) {
        Util.Animate(button1, Util.Effect.Slide, 150, 180);
    }
person Hans Passant    schedule 23.05.2011
comment
Это работает только с ограниченными элементами управления, Ганс? Я попробовал его в форме входа, но похоже, что он исчез и закрыл форму. - person jp2code; 24.05.2011
comment
Я тестировал его на содержащихся элементах управления. Он также должен работать с формами верхнего уровня, однако он будет скрывать форму при первом вызове, поскольку вы вызвали бы Show () для ее отображения. Заменить Show () на анимацию открытия формы сложно, задайте вопрос по этому поводу отдельно. - person Hans Passant; 24.05.2011
comment
Я использую этот код, но он выдает Animation failed исключение, что может быть не так? - person Vahid Nateghi; 11.11.2013
comment
Это действительно полезно! Должен сказать, это решит все мои потребности в анимации. Я получил animation failed исключение при попытке применить стиль смешанной анимации. Не уверен, что это за анимация - person swdev; 24.03.2014
comment
это работает для выдвижения панели, но как сдвинуть панель. - person tariq; 09.11.2014
comment
@tariq, Вы можете сделать это, изменив четвертый параметр при вызове метода Util.Animate, который является углом движения, например: Util.Animate (button1, Util.Effect.Slide, 150, 360); - person oMiD; 10.01.2016

Если вы используете .NET 4 (если не замените Task на Thread), функция, подобная этой, может быть началом:

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

Использование:

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

В качестве действия вы должны отправить некоторую логическую переменную, для которой установлено значение true, чтобы вы знали, что анимация завершена, или какой-то код, который нужно запустить после нее. Остерегайтесь тупиковых ситуаций при вызове с нулевым действием. Вы можете запустить две анимации на одном элементе управления в двух разных направлениях с одинаковой скоростью, и он останется там, где был навсегда, и, конечно же, две анимации одновременно могут заставить элемент управления двигаться бесконечно в каком-то направлении, потому что while никогда не закончится :)

person Marino Šimić    schedule 23.05.2011
comment
очень приятно, спасибо, но почему вы используете _1 _-_ 2_? это дорого, не правда ли? - person jonathana; 12.02.2018
comment
он здесь, чтобы предотвратить исключение при закрытии формы, поскольку вы не можете анимировать удаленную форму. это можно было бы решить более сложным способом, используя форму Closing event и имея задачи, которые можно отменять, и выполняя некоторые другие операторы if вокруг каждого движения, но это, вероятно, будет еще медленнее. - person Marino Šimić; 16.10.2018

Посмотрите библиотеку, которую я написал в прошлом году:

Библиотека анимации WinForm [.Net3.5 +]

Простая библиотека для анимации элементов управления / значений в .Net WinForm (.Net 3.5 и новее). Ключевой кадр (путь) на основе и полностью настраиваемый.

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

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

Это перемещает элемент управления c_control с -100, -100 на первое место за 500 мс.

person Soroush Falahati    schedule 19.05.2016

Для WinForms вы можете начать с того, что расположение панели отключено.

Используйте таймер и в событии Tick медленно перемещайте расположение панели в поле зрения, пока она не окажется в ваших предопределенных координатах.

Есть много способов снять шкуру с кошки, но я бы сделал это так.

person jp2code    schedule 23.05.2011