C# Windows 窗体 Blink 标签
本文关键字:标签 Blink 窗体 Windows | 更新日期: 2023-09-27 18:30:48
在Windows窗体对话框中,我有一个包含近2000行的Listview
。每行都有一个复选框。为了方便用户,我在列表视图上方有两个Labels
来显示任何活动过滤器以及选择(选中)的行数。
为了强调何时更改过滤器或选择,我想使标签闪烁。因此,我扩展了Label
类以支持在文本更改时自动闪烁。但它不起作用!
当我使用Windows.Forms.Timer()
标签时,标签可能会闪烁一两次,但并非总是如此,而且通常最终会被隐藏。
当我使用System.Timers.Timer()
时,即使我使用InvokeRequired
,我也会得到crossthreadException
。
出了什么问题
:(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;
}
}
}
有几个错误,很难调试。 主要问题是您忘记将_blinkCount重置回 0。 非常有害的是,您一遍又一遍地订阅 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;
}
}
}
如注释中所述,以下是在窗体上绘制矩形的基础知识(来自本文):
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);
}
}
}
只需将其放入新形式中,然后观察闪烁的蓝色框:)