在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;
}
}
}
答案 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;
}
}
}