2014-06-06 101 views
1

如果Aero打開,MDI應用程序自Windows Vista以來非常慢。移動MDI窗口似乎滯後,重繪速度非常緩慢。使用Aero在WinForms MDI中禁用GDI「硬件加速」以提高速度

自Windows Vista以來,GDI不再是硬件加速,以簡化新的圖形驅動程序模型。如果您禁用Aero(在Windows 8中無法使用Aero),則會再次像Windows XP一樣快。

使用Microsoft應用程序兼容性管理器,即使啓用了Aero,也可以設置「NoGdiHwAcceleration」標誌以恢復MDI應用程序的速度。

但是,沒有說明如何以編程方式禁用此加速或者如果此兼容性標誌可由代碼觸發。

任何人都知道如何?

回答

0

我實際上可以用另一種更直接的.NET方法解決慢的MDI性能,而不需要任何兼容性標誌。

訣竅是強制雙緩衝到MdiClient控件(這是承載MDI窗口的容器)。

父表單上的MdiClient實例可以通過遍歷其所有控件並檢查其類型來檢索。

// Retrieve the MDI client control on this parent window. 
MdiClient mdiClient = null; 
foreach (Control control in Controls) 
{ 
    mdiClient = control as MdiClient; 
    if (mdiClient != null) 
    { 
     break; 
    } 
} 

強制雙緩衝實際上只可能通過調用保護方法SetStyle,所以我們必須使用反射來從外部調用它。這似乎是非常安全的,因爲SetStyle自.NET 1.1開始可用,並且從那以後沒有更改過。

// Force double buffering on it by calling the protected SetStyle method via reflection. 
MethodInfo setStyleMethod = typeof(MdiClient).GetMethod("SetStyle", 
    BindingFlags.NonPublic | BindingFlags.Instance) 
setStyleMethod.Invoke(mdiClient, object[] { 
    ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, 
    true }); 

性能現在與沒有任何自定義繪圖一樣好。

由於參數爲ControlStyles.ResizeRedraw,整個背景在表單大小更改時會重新繪製,如果您計劃繪製漸變背景,則會很有用。只需使用MdiClient實例上的Paint事件並在那裏進行繪製。

這也使得首先在位圖上繪製所有內容的方法不再需要,因爲雙重緩衝已經在內部實現 - 擺脫一路閃爍。

您可能想要解決的唯一問題是在滾動MdiClient(當Windows位於可見區域之外)時重繪背景。這不會導致Paint事件。這需要更多代碼,請參閱以下答案:How to detect when an MDIClient window has been scrolledWinForms Layered Controls with Background images cause tearing while scrolling

0

您是否嘗試過使用DwmEnableComposition和/或DwmEnableBlurBehindWindow?但是,這似乎確實完全禁用Aero,直到應用程序退出或將其更改回來...

還有一個answer here on SO,它使您看起來像在每個窗口中切換到.net 3.5 SP1或更高版本的SW渲染。

+0

Aero dwmapi方法在這裏沒有幫助,因爲它們只是將玻璃延伸到客戶區域。此外,自Win8以來,EnableComposition已不再起作用,並且它還會禁用系統範圍內的整個Aero界面,這不是我想要的。你提到的硬件加速與WPF有關,而不是WinForms和GDI。 –

+0

哦,你提到過Windows 8的問題,但我沒有意識到這是你正在使用的。如果是這樣的話,我不相信這是可能的。 –

+0

是的,我不喜歡從一開始就在Windows 7/Vista中禁用Aero的應用程序:D –