【问题标题】:Drawing with Winforms用 Winforms 绘图
【发布时间】:2012-01-25 00:35:16
【问题描述】:

我想获得一点 WinForm Graphics 知识,所以我将我的小型 2D 编辑器从 XNA 重写为 WinForm Graphics-only。

现在,我为瓦片集创建了一个新的 UserControl,但正如我所见,Paint 方法仅在控件初始化时调用。因为我想永久重绘我的控件(或者至少通过MouseOver 事件来节省一点性能),我听说Invalidate() 方法让控件重绘自己,但这是方式性能太差了。

有什么方法可以让我的 UserControl 通过代码自行绘制,而不会出现这些性能问题?

【问题讨论】:

    标签: .net windows winforms drawing paint


    【解决方案1】:

    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)。

    【讨论】:

    • 首先 - 感谢您的回答。好吧,也许这不是性能问题,而是我的 MouseMove-Method 等待重新绘制控件的时间?我的控件中有一个 ScrollY 变量,它应该调整图形的位置,并由其侧面的 vScrollbar 进行调整。所以我有一个 vScrollbar_Scroll-Event,它更新 ScrollY 值并调用滚动条的 Invalidate-Method。但这只是非常缓慢。我做错了什么?
    • 好的,多亏了您的建议,我进一步研究并解决了问题。我将 ControlStyles.AllPaintingInWmPaint 和 ControlStyles.OptimizedDoubleBuffer 标志设置为 true 并减少了我的绘画区域并且一切工作都非常顺利。谢谢!
    • @Harald:嗯,是的。双缓冲是平滑 UI 更新的标准方法。通常它是在响应闪烁时指示的,而不是您所描述的“慢”。 AllPaintingInWmPaint 只是意味着控件不会首先通过处理WM_ERASEBKGND 消息并绘制默认颜色来擦除自身。双缓冲由 WinForms 提供。它首先将所有内容绘制到屏幕外缓冲区,然后将该屏幕外缓冲区直接传送到屏幕上。这很有帮助,因为您不会看到所有中间绘画步骤都在此过程中发生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多