如何调用绘画事件?

问题描述 投票:0回答:8

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

如何手动调用(引发)绘画事件?

c# .net winforms events
8个回答
112
投票

在您的表单或控件的方法中,您有 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()

通常,您只需调用

Invalidate()
并让系统将其与其他屏幕更新结合起来。如果你很赶时间,你应该调用
Refresh()
,但是这样你就会冒着由于其他控件(尤其是父控件)失效而连续重绘多次的风险。

Windows(Win32 和 WinForms.Net)处理此问题的正常方法是等待 MessageQueue 运行为空,然后处理所有无效的屏幕区域。这是有效的,因为当某些事物发生变化时,通常会级联到其他事物(控件)也会发生变化。

Update() 最常见的场景是当您在 for 循环中更改属性(例如 label1.Text,这将使标签无效)并且该循环暂时阻塞消息循环时。每当你使用它时,你应该问自己是否不应该使用线程。但答案并不总是肯定的。


52
投票

Invalidate() 方法将导致重绘。

MSDN 链接


6
投票

我发现 Invalidate() 产生了太多的闪烁。这是我的情况。我正在开发的自定义控件通过处理 Paint 事件来绘制其全部内容

this.Paint += this.OnPaint;

此处理程序调用执行实际绘画的自定义例程。

private void OnPaint(object sender, PaintEventArgs e)
{
    this.DrawFrame(e.Graphics);
}

为了模拟滚动,我想在每次按下鼠标左键时光标移动时重新绘制控件。我的第一选择是使用 Invalidate() 如下所示。

private void RedrawFrame()
{
    var r = new Rectangle(
        0, 0, this.Width, this.Height);

    this.Invalidate(r);
    this.Update();
}

控件滚动正常,但闪烁远远超出任何舒适水平。因此,我决定在处理 MouseMove 事件后直接调用我的自定义 DrawFrame() 方法,而不是重新绘制控件。这产生了平滑的滚动,没有闪烁。

private void RedrawFrame()
{
    var g = Graphics.FromHwnd(this.Handle);
    this.DrawFrame(g);
}

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


4
投票

我想你也可以打电话给

Refresh()


2
投票

也许这是一个老问题,这就是为什么这些答案对我不起作用......使用 Visual Studio 2019,经过一番调查,这是我找到的解决方案:

this.InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));

1
投票

调用control.invalidate,将引发绘画事件。


1
投票

刷新可能还会使代码更具可读性,具体取决于上下文。


-2
投票

使用

Control.InvokePaint
你也可以用它来手动双缓冲

© www.soinside.com 2019 - 2024. All rights reserved.