2009-09-05 53 views
23

我有一個非常簡單的WPF窗口 - 它唯一的東西是一個右對齊的按鈕。當我通過拖動左邊界來調整窗口大小時,按鈕會跳躍 - 很多。自己嘗試,來回拖動左邊界。如何解決WPF窗體大小調整 - 控制滯後和黑色背景?

此外,在調整大小期間,黑色背景會暫時暴露。

this問題,我問了一個關於Windows窗體的類似問題。我得到的唯一答案表明,這在WPF中得到了解決,然而,令人驚訝的是,它不僅不是固定的,而且WPF還增加了第二個視覺錯誤 - 臨時的黑色背景。

下面是控制滯後的樣子;發生這種情況時,我被它的頂部邊框調整窗口大小(記錄用相機,因爲屏幕蓋使它不那麼明顯的讓一切慢):

                                                  enter image description here

黑色邊框示例:在調整窗口大小時捕獲此邊框;這只是這樣不到一秒鐘,但它是非常明顯的:

                                      enter image description here

難道我做錯了什麼?如何在調整大小期間讓我的控件在一個位置保持視覺狀態?我怎樣才能避免黑色邊框?

注意:按鈕在正確的位置最終結束了 - 調整大小時,只簡單地跳躍周圍

+0

我剛創建了一個截圖列表來演示這個想法。 – 2011-03-22 10:04:39

+5

這讓我感到震驚。微軟創建了一個美妙的技術來設計漂亮的用戶界面並引入了這個可怕的視覺錯誤。 – 2011-03-22 10:06:38

回答

10

這是基於Wieser Software Ltd第二個解決方案的完整工作代碼。

public partial class MainView : Window 
{ 
    public MainView() 
    { 
     InitializeComponent(); 

     //ensure win32 handle is created 
     var handle = new WindowInteropHelper(this).EnsureHandle(); 

     //set window background 
     var result = SetClassLong(handle, GCL_HBRBACKGROUND, GetSysColorBrush(COLOR_WINDOW)); 
    } 

    public static IntPtr SetClassLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong) 
    { 
     //check for x64 
     if (IntPtr.Size > 4) 
      return SetClassLongPtr64(hWnd, nIndex, dwNewLong); 
     else 
      return new IntPtr(SetClassLongPtr32(hWnd, nIndex, unchecked((uint)dwNewLong.ToInt32()))); 
    } 

    private const int GCL_HBRBACKGROUND = -10; 
    private const int COLOR_WINDOW = 5; 

    [DllImport("user32.dll", EntryPoint = "SetClassLong")] 
    public static extern uint SetClassLongPtr32(IntPtr hWnd, int nIndex, uint dwNewLong); 

    [DllImport("user32.dll", EntryPoint = "SetClassLongPtr")] 
    public static extern IntPtr SetClassLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong); 

    [DllImport("user32.dll")] 
    static extern IntPtr GetSysColorBrush(int nIndex); 
} 
+0

這可以改變顯示的黑色位的顏色。這可以在一定程度上緩解這個問題,這取決於窗口的內容。當然對於複雜的背景(如圖像),顯示的位仍然明顯錯誤,因爲潛在的問題(控制佈局滯後,並且窗口的未上漆部分短暫可見)仍然存在。 – 2013-01-14 14:04:24

1

我認爲臨時的黑色背景是WPF問題,與WPF使用DirectX作爲渲染機制的事實有關,當您調整窗口大小時,它必須使窗口系統與繪圖同步。這也可以解釋爲什麼拖動窗口邊框時按鈕與窗口相關的位置錯位。繪製窗口的非客戶區域比繪製窗口內部的區域慢得多,如果將鼠標快速移動到慢速計算機上,則邊界與窗口內部之間的差異可能會更明顯。

假設這隻發生在啓用了Aero的Vista上,並且它應該在Vista SP1中得到修復。但是,我只是在SP2上進行了測試,而且我仍然看到一點黑色背景,但只有在啓用Aero時纔會出現。我的顯卡非常快,所以它幾乎沒有引人注目。

如果我的分析是正確的,那麼您可以解決您的問題的唯一方法是獲得更快的顯卡或關閉Aero。

+0

謝謝,你的建議可能會使這一點不那麼明顯,但不能完全消除它。問題不在於它可見多久,而是它是否可見......順便說一下,Win7 RTM中也存在這個問題。 – 2009-09-09 13:57:45

+5

我看到WPF4.0和Win7 64bit SP1 – sprocket12 2012-05-17 09:03:57

2

這似乎不可能在WPF的當前版本中。

4

有兩種解決方案,具體說明如下: http://wieser-software.blogspot.co.uk/2012/06/wpf-window-rendering-woes.html

  1. 掛鉤的WndProc和處理WM_ERASEBKGND和借鑑的背景下,或另一種顏色,以滿足您的應用程序的主題系統WINDOW_COLOR。
  2. 呼叫SetClassLong設置窗口類背景畫筆

    SetClassLong(手柄,GCL_HBRBACKGROUND,GetSysColorBrush(COLOR_WINDOW));

+0

這改變了顏色,的確如此,所以+1,但我試圖讓顏色不顯示在第一位。我的意思是,就像GDI那樣,所有事情都是重新繪製的。難道它不是雙緩衝區?:) – 2012-06-13 13:03:50

+0

您可以將玻璃延伸到客戶區以獲得不同的效果,但只有在啓動aero時才起作用。 – 2012-06-14 14:03:54