我想获得一些 WinForm Graphics 知识,因此我正在将我的小型 2D 编辑器从 XNA 重写为仅限 WinForm Graphics。
现在,我为图 block 集创建了一个新的 UserControl,但正如我所见,Paint
方法仅在控件初始化时调用。由于我想永久地重新绘制我的控件(或者至少通过 MouseOver
事件来节省一些性能),我听说 Invalidate()
方法让 Control 重新绘制自身,但这方式性能太差。
有什么方法可以让我的 UserControl 通过代码进行 self 绘制,而不会出现这些性能问题?
最佳答案
Paint
方法不仅仅仅在控件初始化时调用。每次需要重新绘制控件时都会调用它。当然,这是在首次创建控件时发生的。当您的应用程序最小化然后恢复时,当另一个窗口移动到您的应用程序上并遮盖其内容然后被删除时,也会发生这种情况。当您使用 Invalidate
方法或等效方法使控件的工作区无效时,也会发生这种情况。这是在 Windows 开发早期作为性能优化而完成的 - 无需重新绘制未更改的内容!
如果你想强制重新绘制控件,你应该调用 Invalidate
method并指定要重新绘制的客户区的特定区域。
我不知道你所说的“那方式性能太差”是什么意思。 Invalidate
方法不可能慢。它所做的只是设置一个标志,告诉 Windows 您的控件在空闲时需要重绘(不处理任何其他消息)。
如果您想强制 Windows 立即重新绘制控件(无需等待其空闲;Windows 早期内置的另一项性能优化),请调用 Update
method ,这会强制立即重绘所有无效区域。
唯一可能变慢的原因是您的绘图代码在Paint
事件处理程序方法内运行缓慢。显然,如果没有先看到代码,我就无法告诉您如何优化该代码。
Is there anyway to let my UserControl paint itself via code, without having these performance-issues?
Paint
事件正是控件应如何以及在何处进行 self 绘制。这就是它存在的原因。
如果您不在Paint
事件中进行绘制,则下次重新绘制控件时您绘制的任何内容都将被删除(如前所述,可以响应任意数量的预期和意外事件而发生)。
但有时,将临时对象绘制到控件的工作区中是有意义的(例如显示一个拖动矩形以响应 MouseDown
事件)。在这种情况下,您可以获得 Graphics
类的实例(通常作为参数传递给 Paint
事件处理程序方法,并在其上调用方法来执行以下操作)您的绘图)随时。您可以通过调用 CreateGraphics
method 来完成此操作在您的控件上,它返回一个 Graphics
对象。然后,您可以在获得的 Graphics
对象中进行绘制,就像在 Paint
事件处理程序方法中一样。
显然,这不能/不会比 Paint
事件处理程序方法内的绘图代码快(如果这实际上是罪魁祸首),但它会导致屏幕立即更新,而不是在控件空闲且不处理任何其他消息时更新。
我再次重申,这种方法应该仅用于提供即时和临时反馈,因为下次控件被删除时,您绘制的所有内容都将被删除重新绘制。发生这种情况时,将引发 Paint
事件,并且该方法处理程序中的代码将运行,该代码对您在其他一次性场合绘制的内容一无所知。这就是为什么一切都应该发生在 Paint
事件处理程序方法内,并且您应该在以下情况下调用 Invalidate
(也许,尽管不常见,Update
):其他一些事件使得有必要重新绘制。
关于.net - 使用 Winform 绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8996409/