如何在 C# 中为我的控件添加移动效果?

Posted

技术标签:

【中文标题】如何在 C# 中为我的控件添加移动效果?【英文标题】:How can I add moving effects to my controls in C#? 【发布时间】:2011-08-31 10:17:17 【问题描述】:

我的 C# 表单中有一个面板,我有一个按钮。当我单击按钮时,不可见的面板显示。相反,我希望面板移入或滑入。 例如,当您单击组合框时,下拉列表不会弹出。我希望我的面板看起来像那样。我该怎么做?

【问题讨论】:

你用的是wpf的winforms吗? 我喜欢 jQuery 的答案,但它被删除了。 @Henk : 也许它是用 C# 制作的使用 Webbrowser 控件的 winforms 应用程序:P 【参考方案1】:

窗口动画是 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);
    

【讨论】:

这仅适用于包含的控件吗,汉斯?我在登录表单上尝试过,但它看起来消失并关闭了表单。 我在包含的控件上对其进行了测试。它也应该在***表单上工作,但是它会在第一次调用时隐藏表单,因为您已经调用 Show() 来显示它。替换 Show() 以动画形式打开表单很棘手,请单独询问有关它的问题。 我正在使用此代码,但它会抛出 Animation failed 异常,可能是什么问题? 这适用于滑出面板但如何滑入面板。 @tariq,你可以通过改变调用Util.Animate方法中的第四个参数,即移动角度来实现,例如:Util.Animate(button1, Util.Effect.Slide, 150, 360); 【参考方案2】:

如果您使用的是 .NET 4(如果不使用 Thread 替换 Task),则可以使用类似于此的函数:

    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 永远不会结束 :)

【讨论】:

非常好,谢谢,但为什么要使用Try-Catch?很贵吧? 这里是为了防止在关闭表单时出现异常,因为您无法在已处理的表单上设置动画。这可以通过使用表单关闭事件并具有可取消的任务并在每次移动周围执行一些其他 if 语句以更复杂的方式解决,但它可能会更慢。【参考方案3】:

看看我去年写的库:

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 毫秒内的第一个位置。

【讨论】:

【参考方案4】:

对于 WinForms,您可以从不在屏幕上的面板位置开始。

使用计时器,并在 Tick 事件中,将面板的位置缓慢移动到视野中,直到它位于您的预定义坐标处。

给猫剥皮的方法有很多,但我就是这样做的。

【讨论】:

以上是关于如何在 C# 中为我的控件添加移动效果?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查系统上是不是存在电池,然后在 C# 中为我的 WPF 应用程序获取电池百分比

如何在我的可视 C# Web 服务中为我的 android 应用程序调用 LINQ 中的用户定义函数?

如何在 Xcode 中为我的表格视图添加上边距?

如何在 Rails 应用程序中为我的用户添加角色?

我如何在 javascript 中为我的游戏制作图像跟随另一个图像

如何在我的 iphone 中为我的网站添加有效且受信任的安全证书?