2010-03-24 66 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。

這工作就像一種享受。