C#Windows表单闪烁标签

时间:2013-09-09 08:25:03

标签: c# winforms user-interface timer

在Windows窗体对话框中,我有Listview,其中包含近2000行。每行都有一个复选框。为方便用户,我在Listview上方有两个Labels来显示任何活动过滤器以及选择(检查)了多少行。

要强调更改过滤器或选择的时间,我想让标签闪烁。因此,我将Label类扩展为在文本更改时自动支持闪烁。 但它没有用!

当我使用Windows.Forms.Timer()时,标签可能会闪烁一次或两次,但并非总是如此,并且通常最终会隐藏。

当我使用System.Timers.Timer()时,即使我使用crossthreadException,我也会获得InvokeRequired

什么是错的:(

class BlinkLabel : Label
{
    private int _blinkFrequency = 621;
    private int _maxNumberOfBlinks = 15;
    private int _blinkCount = 20;
    private bool _isBlinking = false;
    //System.Timers.Timer _timer = new System.Timers.Timer();
    Timer _timer = new Timer();

    public BlinkLabel(){}
    public BlinkLabel(int frequency, int maxNrBlinks)
    {
        _blinkFrequency = frequency;
        _maxNumberOfBlinks = 15;
    }
    protected override void OnTextChanged(System.EventArgs e)
    {
        base.OnTextChanged(e);
        if (!_isBlinking)
        {
            base.ForeColor = System.Drawing.Color.Purple;
            StartBlink();
        }
    }
    public void StartBlink()
    {
        this._isBlinking = true;
        base.Visible = true;
        this._timer.Interval = this._blinkFrequency;
        this._timer.Enabled = true;
        //this._timer.AutoReset = true;
        //this._timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
        this._timer.Tick += new EventHandler(_timer_Tick);
        this._timer.Start();
    }

    void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        //SYSTEM.TIMERS.TIMER() TICK
        if (this.InvokeRequired)
        {
            this.Invoke(new MethodInvoker(() => { this._timer_Elapsed(sender, e); }));
        }
        else
        {
            base.Visible = !base.Visible;
            this._blinkCount++;
            Application.DoEvents();
            if (this._blinkCount >= this._maxNumberOfBlinks)
            {
                this._timer.Stop();
                this._blinkCount = 0;
                base.Visible = true;
                this._isBlinking = false;
            }
        }
    }

    void _timer_Tick(object sender, EventArgs e)
    {
        //WINDOWS.FORMS.TIMER TICK
        this.Visible = !this.Visible;
        this._blinkCount++;
        Application.DoEvents();
        if (this._blinkCount >= this._maxNumberOfBlinks)
        {
            this._timer.Stop();
            this._blinkCount = 0;
            //base.Visible = true;
            this.Visible = true;
            this._isBlinking = false;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

正如评论中所讨论的,以下是在表单上绘制矩形的基础知识(来自this文章):

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication5
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Get your rectangle size from your text box
        Rectangle tbSize = new Rectangle(10, 10, 50, 20); 

        // invalSize must be slightly bigger due to where the lines are drawn
        Rectangle invalSize = new Rectangle(10, 10, 51, 21); 

        Timer _timer = new Timer();
        bool painting = true;

        private void Form1_Load(object sender, EventArgs e)
        {
            this._timer.Interval = 1000;
            this._timer.Enabled = true;
            this._timer.Tick += new EventHandler(_timer_Tick);
            this._timer.Start();
        }


        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (painting)
            {
                // e.Graphics uses what Windows has decided needs to be repainted
                // eg only the small rectangle we are drawing, or our rect and
                // a control on the other side of the form
                DrawBorderRect(tbSize, e.Graphics); 
            }
        }

        private void DrawBorderRect(Rectangle coords, Graphics dc)
        {
            Pen bluePen = new Pen(Color.Blue, 1);
            dc.DrawRectangle(bluePen, coords);
        }

        private void _timer_Tick(object sender, EventArgs e)
        {
            painting = !painting;

            // This will make Windows raise a paint event so we don't have to.
            // Doing it this way allows Windows to combine multiple small paint
            // events to maximise efficiency
            this.Invalidate(invalSize); 
        }

    }
}

把它扔进一个新的形状,看着闪烁的蓝色框:)

答案 1 :(得分:1)

有几个错误,使调试变得困难。主要问题是您忘记将_blinkCount重置为0.非常有害,您一遍又一遍地订阅Tick事件处理程序,导致Tick事件处理程序为每个tick发送多次。使用Application.DoEvents()尤其错误,也几乎无法进行调试。

重写此代码:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

class BlinkLabel : Label {
    private const int _maxNumberOfBlinks = 2 * 3;
    private int _blinkCount = 0;
    private Timer _timer;
    private Color oldColor;

    public BlinkLabel() {
        this._timer = new Timer();
        this._timer.Tick += new EventHandler(_timer_Tick);
        this._timer.Interval = 621;
    }

    protected override void OnTextChanged(System.EventArgs e) {
        base.OnTextChanged(e);
        if (!this._timer.Enabled && base.IsHandleCreated) StartBlink();
    }

    public void StartBlink() {
        this._blinkCount = 0; 
        base.Visible = true;
        this.oldColor = base.ForeColor;
        base.ForeColor = System.Drawing.Color.Purple; 
        this._timer.Start();
    }

    private void _timer_Tick(object sender, EventArgs e) {
        base.Visible = !base.Visible;
        this._blinkCount++;
        if (this._blinkCount >= _maxNumberOfBlinks) {
            this._timer.Stop();
            base.Visible = true;
            base.ForeColor = oldColor;
        }
    }
}