如何从TCanvas中删除单个图片?

时间:2014-02-07 15:00:51

标签: delphi canvas bitmap delphi-xe3

我的形式是一个透明面板,其中包含一个Canvas(我认为它的实现在这里并不重要;有人告诉我其他情况)。我在这个Canvas上绘制了很多位图,bya使用:

Panel.Canvas.Draw(Image.Left, Image.Top, Image.Picture.Bitmap, Opacity);
//Image is a TImage instance
//Opacity is an integer 0..255

但是当我在TImage中做一些改变时,比如重新定尺寸或在窗体周围移动时,我会在面板中重新调整它的图片。这里的问题是旧的定位图像仍然在画布上。 现在我的问题是:有一种方法可以擦除画布上的单个位图吗?如果是这样,会是什么?如果没有,有办法擦除所有画布的内容?这样我就可以重绘剩余的图片。

编辑:

最后,我的问题出现在我正在使用的透明面板上。它的Paint方法很糟糕,并没有使其画布无效以删除它上面的控件。无论如何,问题解决了。该怎么办?

2 个答案:

答案 0 :(得分:4)

不是真的,因为画布没有跟踪不同的图像。

但是,您可以轻松地“清除”画布的任何部分 这将允许您重绘所有剩余的图片。

如果有很多图片并且用户忙于拖动单张图片,这可能会非常耗时;因为这会导致对运动图像的每次轻微位置变化进行大量重绘。

一种选择是在调整时使用XOR蒙版绘制“活动”图像。然后可以通过再次使用XOR掩码重新绘制在相同位置来擦除它。这样做的缺点是颜色会变形,但效率很高。

另一种选择是制作画布的一部分副本,以便在绘制之前绘制活动画面。然后你有一个简单的机制,通过在正确的位置重新绘制副本来擦除新图片。


编辑:响应Guill评论的最后一个选项的详细说明:

  

我怎么能画它,因为我没有背景?有某种透明刷?

假设您想要绘制和移动图片(可能是20x60的蓝色矩形):

  • 假设您从空白画布开始,clWhite背景。
  • 初始位置是(25,75),所以:
  • (A)首先在画布上复制20x60 Rect(25,75)。
  • 副本当然是全白的,但这正是你背景的样子。
  • 现在在那个位置画出你的矩形。

很酷,先完成一点。现在你想将矩形移动到(40,90):

  • 在(25,75)处绘制复制的图像。 NB 根本没有透明度!在绘制蓝色矩形之前,您希望将Canvas恢复到(A)的状态。
  • 将20x60 Rect复制到(40,90)。 (再次,它将完全是白色)
  • 在(40,90)处绘制蓝色矩形。

好的,到目前为止一直很好,但我们的副本总是白色的。所以让我们添加第二个矩形。 (这次是红色和80x10。)

  • 我们将丢弃当前的副本,因为我们不再想移动蓝色矩形。
  • 我们想将红色矩形放在(45,95)处,因此它与蓝色重叠。
  • (B)将80x10 Rect复制到(45,95)
  • 注意,这次副本的一部分是蓝色,其余部分是白色。
  • 现在在(45,95)
  • 处绘制红色矩形

最后一步,让我们将红色矩形的大小减小到5x5:

  • 绘制复制的图像(45,95)。 NB 再次非常重要的是我们使用透明度,因为我们正在尝试恢复图像中我们将红色矩形绘制回原来的部分在(B)
  • 将5x5 Rect复制到(45,95)
  • 绘制较小的红色矩形。

这是一个简单的漂洗重复过程。碰巧的是,这与Windows在移动时绘制鼠标光标的技术相同。

旁注:如果您正在绘制的图像是不规则形状,则无关紧要。如果您的备用矩形完全覆盖了您正在绘制的图像,则此技术可以正常工作。

答案 1 :(得分:3)

您的整个绘画方法都是错误的。 Windows绘图表面不记得它们的内容。 Windows中的绘画设计要求每个窗口在被询问时能够重新绘制自己,即发送WM_PAINT消息时。您必须通过绘画要求绘画的内容来回复WM_PAINT。您目前违反了该规则。您需要重新设计程序以适应系统。

执行以下操作:

  1. 在您的面板中添加TPaintBox
  2. OnPaint事件处理程序添加到执行所有绘制的绘制框中。
  3. 当您需要强制重新绘画时,请在绘画框上调用Invalidate
  4. 就是这样。请注意,此处未提及WM_PAINT。这是因为VCL将这一切都包含在内,并以更易消化的形式呈现。

    关于这个主题(以及许多其他主题)的必读读物是Petzold的经典书籍,编程Windows。