2009-11-02 720 views
1

我試圖通過使用桌面畫布和直接繪製到整個屏幕來繪製。問題是我無法清除桌面畫布。我已經嘗試將canvas.pen.style設置爲psNotXOR並繪製舊圖像,但不幸的是,這不夠可靠,並且在某些情況下仍然存在一些殘留的圖像。使用Delphi繪製和清除桌面畫布

我的需求是當鼠標懸停在窗口/控件周圍時,繪製一個選擇矩形。

回答

5

你不寫什麼操作系統你清理後的人工製品有問題。

至少在激活桌面組合的情況下,直接繪製桌面並進行異或繪畫是一個非常糟糕的主意(請參閱this blog post中的「繪圖和從屏幕讀取 - Baaaad!」)。除了負面的性能影響,您無法確定其他繪畫同時發生了什麼,以及哪些效果和動畫會改變顯示的內容,因此,簡單的XOR可能不足以完全抹去所有內容。

實現它的一種可能的方式是桌面大小的透明覆蓋窗口,並繪製您的橡皮筋選擇器。如果大小更改應該足夠,則無效整個窗口,不需要擦除舊的選擇線。如果疊加層被刪除,該行也將消失。桌面組成將確保不發生閃爍。但是,在選擇區域時切換應用程序將會出現問題,您需要理解並立即取消選擇。

編輯:

我剛剛與德爾福2009年測試了它,並用下面的測試程序:

  • 形式與FormStyle設置爲fsStayOnTopAlphaBlend設置爲True
  • 與重寫的CreateParams()方法添加WS_EX_TRANSPARENT擴展樣式標誌

我可以將所有鼠標點擊傳遞到底層窗口,同時能夠在頂層窗口中繪製窗口。這應該讓你開始。

+0

我曾考慮過這個問題,但問題在於Windows不會將控制權交還給我。還是會呢?想想看,如果畫布是透明的,這可能會起到訣竅的作用。我會嘗試的。 謝謝你提供非常詳細和有用的答案。 – jonjbar 2009-11-02 19:49:57

+0

那麼,選擇不起作用,頂級窗口始終是鼠標後面的一個窗口。 – jonjbar 2009-11-03 08:29:23

+0

對不起,不明白。你是否通過在桌面上點擊鼠標並開始拖動來開始選擇?如果是這樣,你如何用全局(低級別)鼠標鉤子來捕捉這個問題?或者你是否創建了疊加層(當處於特殊選擇模式時),並通過點擊鼠標開始選擇?也許你可以用更多的細節來擴展你的問題。 – mghie 2009-11-03 08:37:19

0

我在過去做過這樣的事情,我從來沒有想出一個可以接受的解決方案。

雖然您可以向桌面HWND發送無效命令,但請仔細考慮。

因爲在桌面上,你應該能夠使用類似

procedure InvalidateDesktop; 
begin 
    RedrawWindow(GetDesktopWindow, 0, 0, RDW_INVALIDATE); 

    //if that doesn't work then try this: 
    //Sendmessage(GetDesktopWindow, wm_setredraw, 1, 0); 
end; 

這可能會做你想要什麼修改ListView控件,我沒有測試它,因爲我剛剛敲起來的例子。

+0

可見的listview只是'GetDesktopWindow()'返回的'HWND'的子元素,所以這可能不會按原樣工作。 – mghie 2009-11-02 17:09:49

+0

我確實說過我沒有測試過它。 2009-11-02 19:38:35

+0

正如mghie所預料的那樣,這不起作用。謝謝你的回答,瑞恩。 – jonjbar 2009-11-02 19:47:59

-2

這是我們如何做到這一點在我們的應用程序:

FBitmap.Canvas.Brush.Color := clWhite; 
    FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect); 
+0

-1這不是OP要求的「清算」。相反,它只是畫一個白色的矩形。 – jpfollenius 2009-11-02 21:54:08

+0

啊,呃。沒有正確閱讀這個問題。 – 2009-11-03 23:07:00

0

的問題是,Windows將不會返回我的控制鼠標

我覺得背後您需要爲此掛鉤鼠標事件消息 - 掛鉤的消息會爲您提供鼠標懸停的窗口句柄。

查找SetWindowsHookEx(WH_MOUSE ,,,)和MOUSEHOOKSTRUCT。

+0

我已經使用全局鼠標鉤來檢索窗口句柄,但是當我創建頂層窗口時,即使它是透明的,Windows總是選擇它的句柄:( – jonjbar 2009-11-03 08:28:34