C# 如何在自定义控件中使用Control.Update方法
我将首先发布我的代码,因为它简短易懂,然后我会问我的问题C# 如何在自定义控件中使用Control.Update方法,c#,custom-controls,flicker,onpaint,C#,Custom Controls,Flicker,Onpaint,我将首先发布我的代码,因为它简短易懂,然后我会问我的问题 public class BatteryLabel : Control { private Color _captionColor = SystemColors.Control; private Color _textColor = SystemColors.Info; private Color _failColor = Color.Red; private Color _passColor = Colo
public class BatteryLabel : Control
{
private Color _captionColor = SystemColors.Control;
private Color _textColor = SystemColors.Info;
private Color _failColor = Color.Red;
private Color _passColor = Color.Green;
private string _caption;
string text2;
string text3;
bool battery1Fail = false;
bool battery2Fail = false;
bool battery3Fail = false;
public BatteryLabel()
{
}
public Color BackgroundTextColor
{
get{ return _textColor;}
set{_textColor = value; Invalidate();}
}
public string Caption
{
get
{
return _caption;
}
set
{
_caption = value;
Invalidate();
}
}
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
Invalidate();
}
}
public string Text2
{
get { return text2; }
set { text2 = value; Invalidate(); }
}
public string Text3
{
get { return text3; }
set { text3 = value; Invalidate(); }
}
public bool Battery1Fail
{
get { return battery1Fail; }
set { battery1Fail = value; Invalidate(); }
}
public bool Battery2Fail
{
get { return battery2Fail; }
set { battery2Fail = value; Invalidate(); }
}
public bool Battery3Fail
{
get { return battery3Fail; }
set { battery3Fail = value; Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawRectangle(Pens.Black, 0,0, Width-1, Height-1);
var x1 = 50;
var x2 = 98;
var x3 = 146;
var color1 = battery1Fail?_failColor:BackgroundTextColor;
var color2 = battery2Fail?_failColor:BackgroundTextColor;
var color3 = battery3Fail?_failColor:BackgroundTextColor;
e.Graphics.FillRectangle(new SolidBrush(color1),x1+1, 1, 47, Height-2);
e.Graphics.FillRectangle(new SolidBrush(color2),x2+1, 1, 47, Height-2);
e.Graphics.FillRectangle(new SolidBrush(color3),x3+1, 1, 47, Height-2);
e.Graphics.DrawLine(Pens.Black, x1,0, x1, Height-1);
e.Graphics.DrawLine(Pens.Black, x2,0, x2, Height-1);
e.Graphics.DrawLine(Pens.Black, x3,0, x3, Height-1);
var BoldFont = new Font(this.Font, FontStyle.Bold);
e.Graphics.DrawString(Caption, BoldFont, new SolidBrush(ForeColor), 0,0);
e.Graphics.DrawString(Text, this.Font, new SolidBrush(ForeColor), x1,0);
e.Graphics.DrawString(Text2, this.Font, new SolidBrush(ForeColor), x2,0);
e.Graphics.DrawString(Text3, this.Font, new SolidBrush(ForeColor), x3,0);
}
}
控件大小为195,14,以防您决定尝试使用它。我在一个面板中有8个这样的处理器,在1.6Ghz的atom处理器上运行200200。它用于在计算机上显示最多3节电池的值。标签每500毫秒刷新一次。正如你可能已经收集到的,有一点闪烁,但它是可以忍受的。如果可能的话,我只想要更少的。所以我开始研究使用Update,并将一些代码移动,比如我认为应该将其移动到OnPaintBackground(),但在我创建的测试框架中,Update方法不会改变任何内容,当我使用Invalidate方法时,它会同时运行OnPaintBackground和OnPaint。这是我在那个案子里试过的
public class InformationLabel : Control
{
Random r = new Random();
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
Color randomCOlor = Color.FromArgb(r.Next());
e.Graphics.FillRectangle(new SolidBrush(randomCOlor),0,0, Width-1, Height-1);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Color randomCOlor = Color.FromArgb(r.Next());
e.Graphics.FillPie(new SolidBrush(randomCOlor),15,15,15,15, 0.0f, 120.0f);
}
}
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
void Button1Click(object sender, EventArgs e)
{
informationLabel1.Update();
}
void Button2Click(object sender, EventArgs e)
{
informationLabel1.Invalidate();
}
}
我把一个用户控件设置为300300左右,这样我就可以确定我看到了什么。我忘了在我的500毫秒计时器的电池控制中,我只是更新了文本、文本2和文本3。我在想,如果该文本的值超出规范,我将设置电池故障标志,然后使其无效。。但我不确定。那么,我应该如何只更新文本 我相信你找错了消除闪烁的地方。我可以使用你的
BatteryLabel
基本上只需一行就可以实现文本的无闪烁更新。将构造函数更改为如下所示:
public BatteryLabel()
{
this.SetStyle(ControlStyles.OptimizedDoubleBuffer,true);
}
这会告诉控件加倍缓冲其图形,从而使闪烁消失
要以100ms刷新间隔进行测试,请执行以下操作:
Timer t;
public Form1()
{
InitializeComponent();
t = new Timer();
t.Interval = 100;
t.Tick += new EventHandler(t_Tick);
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
string ticks = DateTime.Now.Ticks.ToString();
string ticks1 = ticks.Substring(ticks.Length-4),
ticks2 = ticks.Substring(ticks.Length - 5,4),
ticks3 = ticks.Substring(ticks.Length - 6,4);
batteryLabel1.Text = ticks1;
batteryLabel1.Text2 = ticks2;
batteryLabel1.Text3 = ticks3;
batteryLabel1.Battery1Fail = ticks1.StartsWith("1");
batteryLabel1.Battery2Fail = ticks2.StartsWith("1");
batteryLabel1.Battery3Fail = ticks3.StartsWith("1");
}
这有帮助吗,还是我误解了你的意思?我相信你在错误的地方寻找消除闪烁的方法。我可以使用你的
BatteryLabel
基本上只需一行就可以实现文本的无闪烁更新。将构造函数更改为如下所示:
public BatteryLabel()
{
this.SetStyle(ControlStyles.OptimizedDoubleBuffer,true);
}
这会告诉控件加倍缓冲其图形,从而使闪烁消失
要以100ms刷新间隔进行测试,请执行以下操作:
Timer t;
public Form1()
{
InitializeComponent();
t = new Timer();
t.Interval = 100;
t.Tick += new EventHandler(t_Tick);
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
string ticks = DateTime.Now.Ticks.ToString();
string ticks1 = ticks.Substring(ticks.Length-4),
ticks2 = ticks.Substring(ticks.Length - 5,4),
ticks3 = ticks.Substring(ticks.Length - 6,4);
batteryLabel1.Text = ticks1;
batteryLabel1.Text2 = ticks2;
batteryLabel1.Text3 = ticks3;
batteryLabel1.Battery1Fail = ticks1.StartsWith("1");
batteryLabel1.Battery2Fail = ticks2.StartsWith("1");
batteryLabel1.Battery3Fail = ticks3.StartsWith("1");
}
这是否有帮助,或者我是否误解了您?您可以通过在构造函数中添加以下行来消除闪烁:
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint, true);
现在在绘制处理程序中绘制背景和所有其他内容
优化可以通过传递一个矩形来完成,该矩形仅对需要重新绘制的区域无效。然后在OnPaint覆盖中,使用e.ClipRectangle来确定要绘制的内容。对于如此简单的图形,这可能不是必需的。您可以通过在构造函数中添加以下行来消除闪烁:
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint, true);
现在在绘制处理程序中绘制背景和所有其他内容
优化可以通过传递一个矩形来完成,该矩形仅对需要重新绘制的区域无效。然后在OnPaint覆盖中,使用e.ClipRectangle来确定要绘制的内容。对于这样一个简单的绘图,这可能不是必需的。@Tergiver下面给出了基本相同的解决方案,但添加了两个额外的标志,可能会提高操作效率。这主意不错,因为你实际上是在自己作画。如果您仅使用最小的ControlStyles.OptimizedDoubleBuffer进行尝试,您会发现即使刷新率远高于实际使用的刷新率,它也能正常工作,但没有理由不设置其他标志。我现在有家人,所以无法测试它。但当我这么做的时候,我会让你知道的。这看起来很有希望。下面的Tergiver给出了基本相同的解决方案,但添加了几个额外的标志,可能会提高操作的效率。这主意不错,因为你实际上是在自己作画。如果您仅使用最小的ControlStyles.OptimizedDoubleBuffer进行尝试,您会发现即使刷新率远高于实际使用的刷新率,它也能正常工作,但没有理由不设置其他标志。我现在有家人,所以无法测试它。但当我这么做的时候,我会让你知道的。但这看起来很有希望。