我怎么称油漆事件?

Iva*_*nov 45 .net c# events winforms

我的程序在其面板上绘制文本,但如果我想删除文本,我必须重新绘制.

如何手动调用(加注)绘画事件?

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无效)并且该循环暂时阻止消息循环.无论何时使用它,您都应该问自己是否应该使用线程.但答案并非总是如此.

  • 我想澄清一下.Update()将立即重新绘制已经失效的控件的任何部分.你仍然需要先失效.Refresh()将无效并立即重新绘制整个控件.当我编写一个控件来执行它自己的绘图时,我使用脏矩形调用Invalidate(),然后为了响应而调用Update(),并为了性能而远离Refresh(). (9认同)
  • 请注意,根据您使用的方法,可能存在巨大的 CPU 性能差异。`this.Invalidate()` 需要最少的 CPU 资源,因为您不会强制执行标准消息循环之外的事情,如果您可以调用 `this.Invalidate(false)` 则尤其如此,因此您只调用了 `OnPaint( )` 在主控件/窗体而不是子控件上。对于我的一个 UserControl,从 `this.Update()` 移动到 `this.Invalidate(false)` 将 CPU 负载降低了 4 倍。 (2认同)

Mat*_*nes 43

Invalidate()方法将导致重绘.

MSDN链接


小智 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)

这种方法可能并不适用于所有情况,但到目前为止它很适合我.

  • 使用双缓冲来摆脱闪烁. (3认同)

Bri*_*ian 5

我想你也可以打电话Refresh().