使用计时器和毫秒来淡化表单,但持续时间加倍

Using a timer and milliseconds to fade a form away but the duration is doubled

我正在制作我自己的小自定义消息框,本质上它只是一个小框,显示一条消息 X 时间,然后消失 Y 持续时间。 正在发生的事情是淡出时间是预期的两倍,我无法弄清楚为什么。有人可以看看我的代码并找出为什么它使表单消失所花费的时间比预期的多一倍吗?

    //Initiate and set up the message bubble.
    public static void InitiateBubble(String displayText, Double showTime = 1000, Double fadeTime = 2000) {
        Bubble bubble = new Bubble(displayText);
        bubble.showTime = showTime;
        bubble.fadeTime = fadeTime;
        bubble.Show();
        bubble.showTimer = new Timer();
        bubble.showTimer.Interval = (int)bubble.showTime;
        bubble.showTimer.Tick += bubble.startFadeAway;
        bubble.showTimer.Start();
    }

    //Leaves some time on screen before starting to fade away
    private void startFadeAway(object sender, EventArgs e) {
        showTimer.Stop();
        fadeAwayTimer = new Timer();
        fadeAwayTimer.Interval = 10;
        fadeAwayTimer.Tick += fadeAway;
        fadeAwayTimer.Start();
    }

    //slowly fades the contorle away until it disapears.
    private void fadeAway(object sender, EventArgs e) {
        double opacity = Opacity;
        opacity -= (10 / fadeTime);
        if (opacity < 0) {
            Close();
        }
        else {
            Opacity = opacity;
        }
    }

如果用户将渐变间隔设置为 1 秒(1000 毫秒),而我们将定时器间隔设置为 1/10 秒(100 毫秒),那么我们需要在每个间隔内将不透明度渐变 10% (因为间隔每秒触发 10 次)。所以我们会在每次迭代时设置 Opacity -= .1

如果用户将淡入淡出间隔设置为 2 秒(2000 毫秒),而我们仍然将定时器间隔设置为 1/10 秒,那么我们只需要在每个间隔内将不透明度淡出 5%,所以我们会在每次迭代时设置 Opacity -= .05

看到这个关系,我们可以发现:

var amountToReduceOpacity = 1.0 / fadeTime * interval;

注:如上文γηράσκω δ' αεί πολλά διδασκόμε所述,winform timer的分辨率在17毫秒左右,如果设置小于这个值,淡入淡出会显着减慢,因为我们将计算一个非常快的计时器的速率(这意味着我们不会在每次迭代中衰减太多),但它会执行得更慢。在我的机器上,将其设置为 50 看起来很好。

现在我们可以使用这个公式在每个时间间隔以正确的量淡化表格。这是一个示例 Form,基本上可以完成您上面所做的事情(请注意,我在表单上放置了一个标签和两个计时器,并将它们命名为:lblDisplayshowTimerfadeTimer):

public partial class Bubble : Form
{
    private readonly double amountToReduceOpacity;
    private readonly int fadeInterval = 50; 

    // Custom form constructor takes in all three required settings
    public Bubble(string displayText, int showTime, int fadeTime)
    {
        InitializeComponent();

        lblDisplay.AutoSize = true;
        lblDisplay.Text = displayText;
        lblDisplay.Left = ClientRectangle.Width / 2 - lblDisplay.Width / 2;
        lblDisplay.Top = ClientRectangle.Height / 2 - lblDisplay.Height / 2;

        showTimer.Interval = showTime;
        fadeTimer.Interval = fadeInterval;

        amountToReduceOpacity = 1.0 / fadeTime * fadeInterval;
    }

    // The Shown event starts the first timer
    private void Bubble_Shown(object sender, EventArgs e)
    {
        showTimer.Start();
    }

    // The shownTimer starts the fadeTimer
    private void showTimer_Tick(object sender, EventArgs e)
    {
        showTimer.Stop();
        BackColor = Color.Red; // Just so we see when the fade starts
        fadeTimer.Start();
    }

    // The fade timer reduces opacity on each iteration until it's zero
    private void fadeTimer_Tick(object sender, EventArgs e)
    {
        Opacity -= amountToReduceOpacity;
        if (Opacity <= 0) Close();            
    }
}

然后在客户端我们可以做类似的事情:

private void button1_Click(object sender, EventArgs e)
{
    Bubble bubble = new Bubble("Help me, I'm Fading!", 1000, 2000);
    bubble.Show();
}