我有兩個問題與使用位圖的自己的用戶控制:自己的WinForms控件閃爍並有壞性能
- 它閃爍,如果是通過.NET的「刷新」方法重繪。
- 它有一個糟糕的表現。
控制由三個位圖:
- 靜態背景圖像。
- 旋轉轉子。
- 取決於轉子角度的另一個圖像。
所有使用的位圖的分辨率爲500x500像素。該控件的工作原理如下: https://www.dropbox.com/s/t92gucestwdkx8z/StatorAndRotor.gif(這是一個gif動畫)
用戶控件應該每次獲取新的轉子角度時自行繪製。因此,它具有公共財產「RotorAngle」它看起來像這樣:
public double RotorAngle
{
get { return mRotorAngle; }
set
{
mRotorAngle = value;
Refresh();
}
}
Refresh
引發Paint
事件。該OnPaint
事件處理程序是這樣的:
private void StatorAndRotor2_Paint(object sender, PaintEventArgs e)
{
// Draw the three bitmaps using a rotation matrix to rotate the rotor bitmap.
Draw((float)mRotorAngle);
}
但是,當我使用此代碼 - 這在其他自己的用戶控件效果很好 - 如果控制是通過雙緩衝SetStyle(ControlStyles.OptimizedDoubleBuffer, true)
用戶控件不繪製的。如果我沒有將此標誌設置爲true,則控件在重繪時閃爍。
在控制構造函數中我設置:
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.ContainerControl, false);
// User control is not drawn if "OptimizedDoubleBuffer" is true.
// SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
首先,我認爲它閃爍,因爲背景每次清除控制繪製。所以我設置了SetStyle(ControlStyles.AllPaintingInWmPaint, true)
。但它沒有幫助。
那麼,它爲什麼閃爍?其他控件在此設置下工作得很好。爲什麼如果SetStyle(ControlStyles.OptimizedDoubleBuffer, true)
沒有繪製控制。
我發現,如果我更改屬性RotorAngle
後直接調用我Draw
方法控制不閃爍:
public float RotorAngle
{
get { return mRotorAngle; }
set
{
mRotorAngle = value;
Draw(mRotorAngle);
}
}
但是,這導致非常糟糕的表現,特別是在全屏模式。每20毫秒不可能更新控件。你可以自己嘗試。我將在下面附上完整的Visual Studio 2008解決方案。
那麼,它爲什麼這麼差呢?每20毫秒更新其他(自己的)控件是沒有問題的。這是真的只是由於位圖?
我創建了一個簡單的可視化Visual Studio 2008的解決方案,展示了兩個問題: https://www.dropbox.com/s/mckmgysjxm0o9e0/WinFormsControlsTest.zip(289,3 KB)
有目錄bin\Debug
的可執行文件。
感謝您的幫助。
我不能進入所有的細節了,但你需要看看雙緩衝。幸運的是,它在2008年非常簡單,你在這裏進行刷新的方式也很糟糕。 – Ian
如果您的應用程序可能在遠程桌面上使用,請不要雙緩衝 - 請參閱[此鏈接](http://blogs.msdn.com/b/oldnewthing/archive/2006/01/03/508694.aspx) 。你可以檢查當前會話是否是遠程桌面:'if(SystemInformation.TerminalServerSession)...' – Bridge