2010-03-24 65 views
0

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

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

然后我将子控件放到工具栏上,然后瞧 - 即时工具栏。除了每隔一段时间我都会注意到嵌套(子)控件不会重新绘制。所以我的控件描绘了它的背景,并且在您将鼠标移动到其上方之前,子控件会消失。

一些编辑控件显示其客户区(无边框),其中一些完全消失。

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

我一直认为这必须很容易治愈,也许我不知道如何防止油漆消息到达子控件,或者失去一个覆盖,但我一直无法弄清楚。

回答

1

为了使其正常工作,您最终不需要重画WM_NCPaint中的子控件,可以使用Window的GDI Region函数创建一个剪切区域,该区域排除不想绘制的区域。

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

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

接下来,循环遍历工具栏/面板上顶层的子窗口,并为每个子项调用ExcludeClipRect和适当的坐标。

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

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

+0

我发现了很多东西(请参阅我自己的答案),但是您的解释更好。谢谢! – 2010-03-25 13:38:35

1

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

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

+0

对不起,你失去了我。忘掉工具栏,现在让我们谈谈一个常规的TPanel。如果我在TPanel上打开某些东西,我会希望它重新绘制其可见部分,即使它上面有几个编辑框。工具栏没有什么不同。 – 2010-03-25 07:37:49

+0

你是否在你的WM_PAINT处理程序中放置了一个断点,以便注意到它在Windows控件重新打开之后再次被调用,然后被删除? – 2010-03-25 17:19:04

0

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

这工作就像一种享受。