避免在嵌套控件上绘画

时间:2010-03-24 14:46:53

标签: delphi custom-controls paint

我正在编写一个工具栏样式的控件,并使用ThemeServices单元绘制工具栏所需的背景。像这样:

ThemeServices.DrawElement(Canvas.Handle, 
  ThemeServices.GetElementDetails(trRebarRoot), ARect);

然后我将子控件放到工具栏上,然后瞧 - 即时工具栏。除了我不时地注意到嵌套(子)控件也不会重绘。所以我的控件描绘了它的背景,并且子控件消失,直到你将鼠标移到它们上面。

一些编辑控件显示了他们的客户区域(没有边框),其中一些只是完全消失了。

当我将另一个应用程序的窗口放在工具栏上并将其移开时,会发生这种情况。

我一直认为这必须非常容易治愈,也许我在某种程度上阻止了油漆消息到达子控件,或者错过了覆盖,但我一直无法弄明白。

3 个答案:

答案 0 :(得分:1)

当另一个窗口控件覆盖时,画布必须重新绘制是正常的。

您应该在容器控件的OnPaint事件中绘制工具栏。

答案 1 :(得分:1)

为了使其正常工作以便您不会从WM_NCPaint中过度绘制子控件,您可以使用Window的GDI Region函数创建一个裁剪区域,该区域排除您不想绘制的区域。

您可以通过使用具有背景大小的CreateRectRgn(或类似)函数创建Region来实现此目的。

通过SelectClipRgn函数在您正在使用的DC中选择此区域。

接下来,循环浏览工具栏/面板上的顶级子窗口,并使用适合每个孩子的坐标调用ExcludeClipRect。

最后,当您进行绘画时,只会绘制尚未排除的区域。

另请注意,您可能需要清理您的区域(最好检查GDI帮助)。

答案 2 :(得分:0)

好的,我自己发现了这个问题。我在WM_NCPAINT中绘制背景,因为它是渐变的背景,无法真正一点一点地绘制。我没有意识到WM_NCPAINT通常在没有重新绘制客户端控件的情况下被调用。所以我仍然在WM_NCPAINT中绘制背景,但也在WM_PAINT中绘制背景。后者已被剪裁以排除边界并让前者剪切客户区,我称之为ExcludeClipRect。

这就像一种享受。