按钮的动画发光效果 - C# Windows 表单

Animated Glow Effect for Button - C# Windows Forms

我想在按下按钮时为我的按钮应用动画。在 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 表单没有 Storyboard 和触发器。如何在 Windows 表单中制作流畅的动画?

这是我的 Windows 表单代码:

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

与 winforms 最接近的可能是使其成为 DoubleBuffered。 WinForms 不太适合制作动画。

如果您使用的是自定义控件,请将其添加到 Initialize() 下;

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

否则,在属性中将表单设为DoubleBuffered,或者通过代码:

DoubleBuffered = true;

然后创建动画(如果您还没有弄清楚),循环检查动画是否完成(在计时器事件中)。

基本思路是使用 Timer 并将发光颜色与原始背景颜色进行 alpha 混合。

例如你可以设置FlatStyle of the button to Flat and override OnMouseEnter and OnMouseLeave. In OnMouseEnter start the timer and in and OnMouseLeave stop the timer. In timer Tick event you can set the MouseOverBackColor of FlatAppearance of button to a color which you increase it's alpha channel in Tick事件。

发光按钮代码

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