3

我正在努力学习.NET编程。作为我学习的一部分,我尝试在按钮上制作一些效果。它正在工作......但没有我想象的那么顺利!有没有更好的方法来做到这一点?先感谢您!

我的需要:

有3个按钮。当您将鼠标悬停在其中一个上时,它会展开,当您将鼠标从该按钮移开时,它会返回到其初始大小。

private void button1_MouseHover(object sender, EventArgs e)
    {
        button1.BackColor = Color.White;
        button1.Width = 130;
        button1.BringToFront();            
    }

    private void button1_MouseLeave(object sender, EventArgs e)
    {
        button1.BackColor = Color.Red;
        button1.Width = 75;         
    }

    private void button2_MouseHover(object sender, EventArgs e)
    {
        button2.BackColor = Color.Gray;
        button2.Width = 130;
        button2.BringToFront();            
    }

    private void Form1_MouseLeave(object sender, EventArgs e)
    {
        button2.BackColor = Color.Red;
        button2.Width = 75;

    }

    private void button3_MouseHover(object sender, EventArgs e)
    {
        button3.BackColor = Color.DimGray;
        button3.Width = 130;
        button3.BringToFront();
    }

    private void button3_MouseLeave(object sender, EventArgs e)
    {
        button3.BackColor = Color.Red;
        button3.Width = 75;

    }
4

3 回答 3

6

所以首先,你不想做同样的事情 3 次。创建一个方法来为按钮添加适当的处理程序,然后只需编写一次代码来处理任何给定的按钮。

请注意,您可以进入扩展/收缩刻度处理程序并使用该percentComplete值来设置高度,沿光谱移动颜色(这将涉及一些颜色数学)或更改任何其他方面按钮。如果你真的有动力去概括它,你可以在方法中添加一个参数,Action<double>根据给定的进度百分比对对象做一些事情。

public void AddAnimation(Button button)
{
    var expandTimer = new System.Windows.Forms.Timer();
    var contractTimer = new System.Windows.Forms.Timer();

    expandTimer.Interval = 10;//can adjust to determine the refresh rate
    contractTimer.Interval = 10;

    DateTime animationStarted = DateTime.Now;

    //TODO update as appropriate or make it a parameter
    TimeSpan animationDuration = TimeSpan.FromMilliseconds(250);
    int initialWidth = 75;
    int endWidth = 130;

    button.MouseHover += (_, args) =>
    {
        contractTimer.Stop();
        expandTimer.Start();
        animationStarted = DateTime.Now;
        button.BackColor = Color.DimGray;
    };

    button.MouseLeave += (_, args) =>
    {
        expandTimer.Stop();
        contractTimer.Start();
        animationStarted = DateTime.Now;
        button.BackColor = Color.Red;
    };

    expandTimer.Tick += (_, args) =>
    {
        double percentComplete = (DateTime.Now - animationStarted).Ticks
            / (double)animationDuration.Ticks;

        if (percentComplete >= 1)
        {
            expandTimer.Stop();
        }
        else
        {
            button.Width = (int)(initialWidth +
                (endWidth - initialWidth) * percentComplete);
        }
    };

    contractTimer.Tick += (_, args) =>
    {
        double percentComplete = (DateTime.Now - animationStarted).Ticks
            / (double)animationDuration.Ticks;

        if (percentComplete >= 1)
        {
            contractTimer.Stop();
        }
        else
        {
            button.Width = (int)(endWidth -
                (endWidth - initialWidth) * percentComplete);
        }
    };
}
于 2013-01-16T19:08:16.560 回答
4

如果您使用的是WinForms,动画将相当痛苦,您必须自己通过Timer对象来处理它们。

如果您正在进入 .NET 并希望使用动画和样式制作看起来很酷的应用程序,我强烈建议您改用WPF。它可以通过C#XAML轻松制作动画。

虽然在 WinForms 中仍然可以使用,但由于这些功能已经内置到 WPF 中(并已优化),因此需要更多的开发时间。

于 2013-01-16T19:12:50.093 回答
0

当您修改控件属性时,它会立即生效。您想要的是通常被称为某种类型的淡入淡出或补间的东西。可能有一些库可以做到这一点,但如果您想自己编写这个以取乐,您可以使用 Timer 对象,并在每次滴答时更新颜色。

您要做的是在某处将颜色设置为 TargetColor(这是您编写的变量或属性),然后启动一个可能每 10 毫秒计时一次的计时器。在每个滴答声中,您都会查看开始时间,以及从那时起已经过去了多长时间。如果您希望动画发生一整秒,那么就是 1000 毫秒。因此,在每个滴答声中,您查看已经过去的时间量,可能是 200 毫秒,然后除以 200/1000 以获得您进入动画的时间比例。然后查看起始颜色和目标颜色之间的差异,将该差异乘以分数,然后将结果添加到起始颜色。换句话说,一个持续 1000 毫秒的动画播放 200 毫秒,意味着你有 20% 的时间进入了动画。

你可以做很多事情来完善它。也许有一个子类 Button 控件,它封装了计时器并公开了函数/属性来跟踪开始/结束颜色、动画过渡时间等。大多数像这样的动画 UI 功能让您指定动画应该持续多长时间,然后它插入中间状态,因为它转换。这就是补间这个术语的由来,因为它来自于通过 inbetweening 从一种状态过渡到另一种状态

于 2013-01-16T19:09:38.430 回答