Hen*_*man 89
在表单或控件的方法中,您有3个选择:
this.Invalidate(); // request a delayed Repaint by the normal MessageLoop system
this.Update(); // forces Repaint of invalidated area
this.Refresh(); // Combines Invalidate() and Update()
Run Code Online (Sandbox Code Playgroud)
通常,您只需调用Invalidate()并让系统将其与其他屏幕更新结合使用.如果你赶时间,你应该打电话,Refresh()但由于其他控件(特别是父母)无效,你会冒着连续几次重新粉刷的风险.
Windows(Win32和WinForms.Net)处理此问题的正常方法是等待MessageQueue运行为空,然后处理所有无效的屏幕区域.这是有效的,因为当某些变化通常会逐渐变为其他事物(控件)时也会发生变化.
Update()最常见的情况是在for循环中更改属性(例如,label1.Text,这将使Label无效)并且该循环暂时阻止消息循环.无论何时使用它,您都应该问自己是否应该使用线程.但答案并非总是如此.
小智 8
我发现Invalidate()创建了太多的闪烁.这是我的情况.我正在开发的自定义控件通过处理Paint事件来绘制其全部内容.
this.Paint += this.OnPaint;
Run Code Online (Sandbox Code Playgroud)
此处理程序调用执行实际绘制的自定义例程.
private void OnPaint(object sender, PaintEventArgs e)
{
this.DrawFrame(e.Graphics);
}
Run Code Online (Sandbox Code Playgroud)
为了模拟滚动,我想在每次按下鼠标左键时光标移动时重新绘制控件.我的第一选择是使用Invalidate(),如下所示.
private void RedrawFrame()
{
var r = new Rectangle(
0, 0, this.Width, this.Height);
this.Invalidate(r);
this.Update();
}
Run Code Online (Sandbox Code Playgroud)
控件滚动好,但闪烁远远超出任何舒适的水平.所以我决定在处理MouseMove事件后直接调用我的自定义DrawFrame()方法,而不是重新绘制控件.这产生了平滑滚动而没有闪烁.
private void RedrawFrame()
{
var g = Graphics.FromHwnd(this.Handle);
this.DrawFrame(g);
}
Run Code Online (Sandbox Code Playgroud)
这种方法可能并不适用于所有情况,但到目前为止它很适合我.