在工作中需要做一個伸縮控件,這個自定義控件繼承於Panel。這個伸縮控件分為兩個部分,頭部是一個自定義組件,伸縮控件的背景為灰色,頭部背景要求白色。伸縮控件在點擊按鈕時會重繪,同時他內部的控件也會重繪,這樣就導致伸縮時界面會閃爍。
設置雙緩存不能滿足要求。
有一個解決方案的思路是使得某個控件的繪制背景圖方法(OnPaintBackground方法)直接放回,不調用基類的該方法,同時重寫繪制方法(OnPaint方法)用圖片一次性繪制到背景。要求設置背景圖片。
/// <summary> /// 加強版 Panel /// </summary> class PanelEnhanced : Panel { /// <summary> /// OnPaintBackground 事件 /// </summary> /// <param name="e"></param> protected override void OnPaintBackground(PaintEventArgs e) { // 重載基類的背景擦除函數, // 解決窗口刷新,放大,圖像閃爍 return; } /// <summary> /// OnPaint 事件 /// </summary> /// <param name="e"></param> protected override void OnPaint(PaintEventArgs e) { // 使用雙緩沖 this.DoubleBuffered = true; // 背景重繪移動到此 if (this.BackgroundImage != null) { e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; e.Graphics.DrawImage( this.BackgroundImage, new System.Drawing.Rectangle(0, 0, this.Width, this.Height), 0, 0, this.BackgroundImage.Width, this.BackgroundImage.Height, System.Drawing.GraphicsUnit.Pixel); } base.OnPaint(e); } }
基於這個思路,如果控件的背景是純色,可以自己繪制一個位圖作為背景圖片,進行填充。
protected override void OnPaintBackground(PaintEventArgs e) { // 基類的方法不能用, 防止點擊伸縮時重繪背景導致閃爍 return; } protected override void OnPaint(PaintEventArgs e) { /* 創建一個白色背景的位圖作為背景,防止點擊伸縮時重繪背景導致閃爍。 * 不可在初始化的時候繪制該背景位圖, * 因為容器自適應於父控件的長寬,初始化時候的長寬不一定是最終長寬。 * 所以每次觸發繪制方法的時候都要重新讀取控件的長寬以便重繪位圖 */ Bitmap bmp = new Bitmap(this.Width, this.Height); using (Graphics graph = Graphics.FromImage(bmp)) { Rectangle ImageSize = new Rectangle(0, 0, this.Width, this.Height); graph.FillRectangle(Brushes.White, ImageSize); } e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; e.Graphics.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, this.Width, this.Height), 0, 0, this.Width, this.Height, System.Drawing.GraphicsUnit.Pixel); ////基類的OnPaint方法不能使用,防止點擊伸縮時重繪背景導致閃爍 //base.OnPaint(e); }