2013-01-08 112 views
1

我有以下代碼來拖動窗體,並使其拖動時透明。問題在於它閃爍並且沒有順利拖動。我在表格上有一張照片,不知道這是什麼原因造成的。我怎樣才能讓它不閃爍。如果我刪除不透明度,那麼它會變得很快/很平滑。拖動不透明窗體?

[DllImportAttribute("user32.dll")] 
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, 
    int lParam); 
[DllImportAttribute("user32.dll")] 
public static extern bool ReleaseCapture(); 

public void Drag(MouseEventArgs e) 
{ 
    if (e.Button == MouseButtons.Left) 
    { 
     this.Opacity = 0.9; 
     ReleaseCapture(); 

     SendMessage(Handle, 0xA1, 0x2, 0); 
     this.Opacity = 1; 
    } 
} 

private void Body_MouseDown(object sender, MouseEventArgs e) 
{  
    Drag(e); 
} 
+0

一般來說,GDI(Windows窗體基於什麼)不能很好地處理不透明度,它必須將渲染產品的所有像素與下面的所有圖層混合。 WPF(因爲它依賴於Direct X,它可以在硬件級別執行此操作)通常會使這種操作更好。 – casperOne

+0

Gocha。所以沒有辦法解決這個問題? – Kristian

+1

您可以嘗試將'this.Opacity = 1;'移動到窗體的'ResizeEnd',當您停止拖動窗體時調用該窗體。讓我知道這是否有幫助。請讓我們知道您在此表單上有多少個控件。還請寫出您使用的Windows版本(我認爲在Vista或Win7上可能看不到閃爍)。 –

回答

3

Form和Control類有很多屬性是「沉重的」,需要在底層本地Windows窗口中進行大量更改。它們是與傳遞給本機CreateWindowEx()調用的樣式標誌關聯的屬性。不透明度屬性與TransparencyKey屬性一樣,當您將其從默認值更改爲默認值時,該窗口需要另一個樣式標誌WS_EX_LAYERED。

這是一個問題,因爲當您創建窗口時指定了此樣式標誌。在使用SetWindowsLongPtr()創建窗口之後,Windows有一些支持來改變它們,但這一直是不確定的。對於WS_EX_LAYERED尤其如此,當開啓時,很多東西都在幕後發生。它通過利用稱爲「圖層」的視頻適配器中的硬件功能來實現。一層是一個獨立的視頻內存塊,其像素與主內存相結合。支持該混音器的混音器提供不透明效果(乘法)和透明度效果(省略)。

因此,在創建窗口之後即時更改不透明度屬性非常困難。太多以至於WPF完全禁止它。但是Winforms並沒有,它需要處理Windows 98的侷限性。這也使得很難改變像ShowInTaskbar,RightToLeft,FormBorderStyle這樣的屬性。它使用技巧來允許更改這些屬性,它會使用新樣式標誌完全銷燬本機窗口並重新創建它。

問題解決了,但這確實有明顯的副作用。不可避免的是,你看的窗口消失了,新的窗口被創建並繪製在同一個地方。這會導致你抱怨的閃爍。另外,破壞窗口會導致很多內部狀態丟失。 Winforms盡其所能恢復該狀態以及它可以用於新窗口,但「我目前正在移動」狀態無法恢復。模態移動循環已經終止。

此問題的解決方法很簡單但很簡單。將「屬性」窗口中的「不透明度」屬性設置爲99%。並且改變你的代碼,將它恢復到99而不是100.現在風格位永遠不需要改變,所以你不會再得到這些工件。