Paint 方法不仅在控件初始化时调用。每次需要重新绘制控件时都会调用它。当然,这发生在首次创建控件时。当您的应用程序被最小化然后恢复时,当另一个窗口被移动到您的应用程序上时,它会隐藏其内容然后被删除,等等,也会发生这种情况。当您使用Invalidate 方法或等效方法使控件的客户区无效时,也会发生这种情况。这是在 Windows 开发早期作为性能优化完成的 - 无需重新绘制未更改的内容!
如果要强制重绘控件,应调用Invalidate method 并指定要重绘的客户区的特定区域。
我不明白你所说的“那是方式太低效了”。 Invalidate 方法不可能很慢。它所做的只是设置一个标志,告诉 Windows 您的控件在空闲时需要重绘(不处理任何其他消息)。
如果你想强制 Windows立即重新绘制你的控件(而不是等待它空闲;Windows 早期内置的另一个性能优化),调用Update method,它会强制立即重绘所有无效区域。
如果你的 绘图 代码在 Paint 事件处理程序方法中很慢,唯一可能会变慢的方法。很明显,我不能告诉你如何在不先看到代码的情况下优化它。
有没有办法让我的 UserControl 通过代码自己绘制,而不会出现这些性能问题?
Paint 事件正是控件绘制自身的方式和位置。这就是它存在的原因。
如果您不在 Paint 事件中进行绘制,则您绘制的任何内容都将在下次重新绘制控件时被删除(如前所述,这可能会发生在响应任意数量的预期和意外事件)。
不过,有时将临时对象绘制到控件的客户区是有意义的(例如显示一个拖动矩形以响应MouseDown 事件)。在这种情况下,您可以随时获取Graphics 类的实例(通常作为参数传递给Paint 事件处理程序方法,并在其上调用方法进行绘图)。您可以通过调用控件上的CreateGraphics method 来执行此操作,这将返回一个Graphics 对象。然后,您可以像在 Paint 事件处理程序方法中一样,在获得的 Graphics 对象中绘制/绘制。
显然这不能/不会比 Paint 事件处理程序方法中的绘图代码快(如果这实际上是罪魁祸首),但它会导致屏幕更新 立即 而不是在控件空闲且不处理任何其他消息时。
我将再次重申,这种方法应该仅用于提供即时和临时反馈,因为您绘制的所有内容都将在下次控制时被删除重绘。发生这种情况时,会引发Paint 事件,并且您在该方法处理程序中的代码运行,它不知道您在其他一次性场合绘制的内容。这就是为什么所有事情都应该发生在 Paint 事件处理程序方法中的原因,并且当某些其他事件需要重新绘制时,您应该调用 Invalidate(虽然不常见,但可能是 Update)。