用Winforms绘图

我想让自己有一点WinFormgraphics知识,所以我将我的小2D编辑器从XNA改写为WinForm Graphics-only。

现在,我为tileset创build了一个新的UserControl,但正如我所看到的, Paint方法仅在控件初始化时被调用。 因为我想永久重绘我的控制(或至less通过MouseOver事件来保存一点性能),我听到Invalidate()方法获取控制重绘本身,但这太不正常。

有什么办法让我的UserControl通过代码绘制自己,而没有这些性能问题?

Solutions Collecting From Web of "用Winforms绘图"

Paint方法不仅在控件初始化时被调用。 每次需要重新绘制控件时,都会调用它。 这当然是在控件第一次创建时发生的。 当你的应用程序被最小化,然后恢复时,当另一个窗口被移到你的应用程序上,使得它的内容变得模糊,然后被删除,等等。 当您使用Invalidate方法或等价方法使控件的客户区失效时也会发生这种情况。 这在Windows的开发早期作为性能优化完成 – 没有必要重新绘制没有改变的东西!

如果要强制重新绘制控件,则应调用Invalidate方法并指定要重新绘制的客户区的特定区域。

我不知道你的意思是“那太不正常了”。 Invalidate方法不可能慢。 它所做的就是设置一个标志,告诉Windows你的控制需要重新绘制,每当它闲置(不处理任何其他消息)。

如果您希望强制Windows 立即重新绘制控件(无需等待它处于空闲状态;从早期版本到Windows的另一个性能优化),请调用Update方法 ,这将强制立即重绘所有失效的区域。

如果您的绘图代码在Paint事件处理程序方法内部速度较慢,则可能会很慢。 显然,我不能告诉你如何优化代码而不先看。


无论如何,让我的UserControl通过代码绘制自己,而没有这些性能问题?

Paint事件正是控件应该如何以及在哪里绘制自己。 这就是为什么它在那里。

如果不在 Paint事件中绘制,则在下次重新绘制控件时(如前所述,可以响应任意数量的预期和意外事件),将Paint所有内容都将被删除。

有时候,将临时对象绘制到控件的客户区(例如响应MouseDown事件显示拖动矩形)是有意义的。 在这种情况下,您可以随时获得Graphics类的实例(通常作为参数传递给Paint事件处理程序方法,并在其上调用方法来执行绘图)。 您可以通过调用控件的CreateGraphics方法来完成此操作,该方法返回一个Graphics对象。 然后,您可以绘制到Graphics对象上,就像在Paint事件处理程序方法中一样。

很显然,这不能比Paint事件处理方法中的绘图代码更快(如果这实际上是罪魁祸首),但它会导致屏幕立即更新而不是每当控件空闲而不处理任何其他消息。

我将再次重申,这种方法只能用于提供即时和临时的反馈,因为下一次重绘控件时,所有绘制的内容都将被删除。 当发生这种情况时,会引发Paint事件,并在该方法处理程序中运行您的代码,这对您在其他一次性事件中绘制的内容不知道。 这就是为什么一切都应该发生在Paint事件处理程序方法内部的情况下,当其他事件需要重新绘制时,您应该调用Invalidate (也许通常不会Update )。