Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我怎么称呼绘画活动?_C#_.net_Winforms_Events - Fatal编程技术网

C# 我怎么称呼绘画活动?

C# 我怎么称呼绘画活动?,c#,.net,winforms,events,C#,.net,Winforms,Events,我的程序在面板上绘制文本,但是如果我想删除文本,我必须重新绘制 如何手动调用(引发)绘制事件?Invalidate()方法将导致重新绘制 调用control.invalidate,将引发绘制事件。我认为您也可以调用刷新()在窗体或控件的方法中,您有3种选择: this.Invalidate(); // request a delayed Repaint by the normal MessageLoop system this.Update(); // forces Repa

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

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

Invalidate()方法将导致重新绘制


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

我认为您也可以调用
刷新()

在窗体或控件的方法中,您有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)处理此问题的正常方式是等待空运行,然后处理所有无效的屏幕区域。这是有效率的,因为当某些事情发生变化时,通常会级联到其他事情(控制)中


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

根据上下文的不同,刷新可能会使代码更具可读性。

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

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

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);
}

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

使用
控制。InvokePaint
您也可以将其用于手动双缓冲

也许这是一个老问题,这就是为什么这些答案对我不起作用的原因。。。使用Visual Studio 2019,经过一些调查,我发现了以下解决方案:

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

我想澄清一下。Update()将立即重新绘制控件中已失效的任何部分。你仍然需要先失效。Refresh()将使整个控件无效并立即重新绘制。当我编写一个自己绘制的控件时,我会用一个脏矩形调用Invalidate(),然后调用Update()以获得响应,而为了提高性能,请远离Refresh()。请注意,根据使用的方法,CPU性能可能会有很大的差异
this.Invalidate()
所需的CPU资源最少,因为您没有强制执行标准消息循环之外的内容,如果您可以调用
this.Invalidate(false)
则尤其如此,因此您只在主控件/窗体上调用
OnPaint()
,而不是在子控件上调用。对于我的一个用户控件,从
this.Update()
移动到
this.Invalidate(false)
将CPU负载减少了4倍。小心,我认为FromHwnd()的结果应该再次处理(将其放在
using(){}
)使用双缓冲来消除闪烁。private void Form1\u Paint(对象发送器,System.Windows.Forms.PaintEventArgs e){System.Drawing.Graphics Graphics Graphics=this.CreateGraphics();System.Drawing.Rectangle Rectangle=new System.Drawing.Rectangle(0,0,50,50);Graphics.DrawEllipse(System.Drawing.Pens.Black,Rectangle);Graphics.DrawRectangle(System.Drawing.Pens.Red,rectangle);}何时调用此绘制方法来重新绘制窗体。它确实重新绘制窗体,不是吗。
this.InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));