按钮的动态发光效果 - C# Windows窗体

5

我想在按下按钮时为我的按钮应用动画。在WPF中,我可以使用带有触发器的Storyboard来创建动画。以下是一个例子:

<Storyboard x:Key="AniOpacityDelay">
  <DoubleAnimation
    Storyboard.TargetName="background"
    Storyboard.TargetProperty="Opacity"
    AutoReverse="True"
    To="0.65"
    Duration="0:0:0.2"/>
</Storyboard>

并且:

<ColorAnimationUsingKeyFrames
  Storyboard.TargetName="Itemcont"
  Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">

  <EasingColorKeyFrame KeyTime="0" Value="#EEEEEE"/>
</ColorAnimationUsingKeyFrames>

Windows Forms没有Storyboard和触发器。那么如何在Windows Forms中实现平滑的动画效果呢?

以下是我在Windows Forms中的代码:

void DelayTime()
{
  timer = new Timer();
  timer.Interval = (int)System.TimeSpan.FromSeconds(this.DelayTime).TotalMilliseconds;
  timer.Tick += (s, es) =>
  {
    this.mouseover = false; 
    this.Cursor = Cursors.Hand;
    this.Enabled = true;
  };
  timer.Start();
}

protected override void OnMouseDown(MouseEventArgs mevent)
{
  base.OnMouseDown(mevent);
  mouseover = true;
  this.Enabled = false;
  DelayTime();
}

protected override void OnPaint(PaintEventArgs e)
{
  Color bg = this._Background;
  bg = mouseover ? this._HoverColor : this._Background;
  e.Graphics.FillRectangle(new SolidBrush(bg), this.ClientRectangle);
}

4
WinForms 在这方面表现得不太好。 - Maarten
对于毫无用处的华丽效果,请继续使用WPF。 - TaW
是的,WPF很好。但问题是我没有一台好电脑。我可能会就任务和性能提出一个新问题。@TaW @Maarten - Jandy
在Windows Forms中实现平滑动画闪烁效果对按钮并不难。 - Reza Aghaei
2个回答

7
基本思路是使用一个计时器,并将发光颜色与原始背景颜色进行alpha混合。
例如,您可以将按钮的 FlatStyle 设置为 Flat 并覆盖 OnMouseEnterOnMouseLeave。在 OnMouseEnter 中启动计时器,在 OnMouseLeave 中停止计时器。在计时器的 Tick 事件中,您可以将按钮的 FlatAppearanceMouseOverBackColor 设置为一种颜色,该颜色的 alpha 通道在 Tick 事件中增加。

Glow Button

发光按钮代码

using System;
using System.Drawing;
using System.Windows.Forms;
public class GlowButton : Button
{
    Timer timer;
    int alpha = 0;
    public Color GlowColor { get; set; }
    public GlowButton()
    {
        this.DoubleBuffered = true;
        timer = new Timer() { Interval = 50 };
        timer.Tick += timer_Tick;
        this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        this.GlowColor = Color.Gold;
        this.FlatAppearance.MouseDownBackColor = Color.Gold;
    }
    protected override void OnMouseEnter(EventArgs e)
    {
        base.OnMouseEnter(e);
        this.FlatAppearance.MouseOverBackColor = CalculateColor();
        timer.Start();
    }
    protected override void OnMouseLeave(EventArgs e)
    {
        base.OnMouseLeave(e);
        timer.Stop();
        alpha = 0;
        this.FlatAppearance.MouseOverBackColor = CalculateColor();
    }
    void timer_Tick(object sender, EventArgs e)
    {
        int increament = 25;
        if (alpha + increament < 255) { alpha += increament; }
        else { timer.Stop(); alpha = 255; }
        this.FlatAppearance.MouseOverBackColor = CalculateColor();
    }
    protected override void Dispose(bool disposing)
    {
        if (disposing) timer.Dispose();
        base.Dispose(disposing);
    }
    private Color CalculateColor()
    {
        return AlphaBlend(Color.FromArgb(alpha, GlowColor), this.BackColor);
    }
    public Color AlphaBlend(Color A, Color B)
    {
        var r = (A.R * A.A / 255) + (B.R * B.A * (255 - A.A) / (255 * 255));
        var g = (A.G * A.A / 255) + (B.G * B.A * (255 - A.A) / (255 * 255));
        var b = (A.B * A.A / 255) + (B.B * B.A * (255 - A.A) / (255 * 255));
        var a = A.A + (B.A * (255 - A.A) / 255);
        return Color.FromArgb(a, r, g, b);
    }
}

我现在正在使用WPF,但是哇,好主意。我需要记下来。如果可以的话+2 @Reza Aghaei - Jandy
感谢您的反馈 :) 是的,这很好,您还可以在不将样式设置为平坦的情况下应用这种技术,只需通过定时器关闭可视样式背景颜色并更改BackColor即可。 - Reza Aghaei

1
最接近WinForms的方法可能是将其设置为DoubleBuffered。WinForms不太适合动画效果。
如果您正在使用自定义控件,请在Initialize()下添加以下内容;
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

否则,可以在属性中或代码中将表单设为DoubleBuffered:
DoubleBuffered = true;

如果您还没有弄清楚,那么创建动画的方法是,在计时器事件中循环检查动画是否完成。


DoubleBuffered = true; 在 Form 上,DelayTime 等于 1.2 似乎很好。但仍然很快。@PaddiM8 - Jandy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接