我實際上可以用另一種更直接的.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 scrolled和WinForms Layered Controls with Background images cause tearing while scrolling
Aero dwmapi方法在這裏沒有幫助,因爲它們只是將玻璃延伸到客戶區域。此外,自Win8以來,EnableComposition已不再起作用,並且它還會禁用系統範圍內的整個Aero界面,這不是我想要的。你提到的硬件加速與WPF有關,而不是WinForms和GDI。 –
哦,你提到過Windows 8的問題,但我沒有意識到這是你正在使用的。如果是這樣的話,我不相信這是可能的。 –
是的,我不喜歡從一開始就在Windows 7/Vista中禁用Aero的應用程序:D –