如何仅使绘制框/位图的一部分无效以优化其性能?

时间:2014-08-27 18:52:19

标签: delphi lazarus

问题涉及:Drawing on a paintbox - How to keep up with mouse movements without delay?

我曾经在某个时候询问过如何重绘油漆箱的一部分而不会使整个油漆箱失效的问题,当有大量的绘图时,这种情况很慢,或者在我的情况下有很多在屏幕上绘制的瓷砖。

Peter Kostov上方的链接中,他的一条评论中简要介绍了该主题:

  

你可以部分BitBlt屏幕外的位图(只有它被更改的区域)。这将大大提高性能。

我的图形技能有限,之前从未真正使用BitBlt,但在发布此问题后,我会更多地阅读它。

话虽如此,我想知道你究竟如何确定位图的区域是否已经改变了?这是否涉及一些简单的事情,还是有更多的魔法可以说参与确定哪些地区发生了变化?

现在我仍然直接绘制到绘图框但是一旦我绘制到屏幕外缓冲区位图,我的下一步就是优化绘画,上面的注释听起来就像我需要的那样,只有已经改变的确定区域已经混淆了我稍微。

当然,如果有其他方法可以这样做,请随时发表评论。

感谢。

2 个答案:

答案 0 :(得分:4)

如果您在屏幕外TBitmap进行绘制,则不必直接使用BitBlt(),而是可以使用TCanvas.CopyRect()(内部使用StretchBlt())。但无论哪种方式,当您需要使TPaintBox的一部分无效(与您绘制的屏幕外位图部分对应的部分)时,您可以直接使用InvalidateRect()来指定相应的矩形TPaintBox的调用,而不是调用TControl.Invalidate()(调用InvalidateRect()并将lpRect参数设置为NULL)。每当触发TPaintBox.OnPaint事件时,InvalidateRect()将在画布中建立剪切矩形,您在该矩形之外所做的任何绘图都将被忽略。如果要手动优化绘图,可以使用TCanvas.ClipRect属性确定需要绘制的TPaintBox矩形,并从屏幕位图中复制该部分。

唯一的问题是TPaintBoxTGraphicControl后代,所以它没有自己的HWND可以传递给InvalidateRect()。您必须使用其Parent.Handle HWND。这意味着您需要将TPaintBox - 相对坐标转换为Parent - 相对坐标,反之亦然。

答案 1 :(得分:2)

你需要掌控这幅画才能做到这一点:

  • 调用InvalidateRect使窗口的某些部分无效。
  • 处理WM_PAINT时,调用BeginPaint会产生一个包含要绘制的矩形的绘制结构。

所有这一切都需要一个窗口,不幸的是,TPaintBox没有窗口。所以你可以使用父控件的窗口句柄,但坦率地说使用窗口控件会更清晰。

您可以使用此问题的窗口绘制控件作为起点:How could I fade in/out a TImage?在绘画时使用控件画布的ClipRect来确定需要重新绘制的画布部分-绘画。