2012-02-21 44 views
1

我不知道爲什麼會發生這種情況,但我創建了下面的代碼,這是一個漸變面板,面板然後停靠在屏幕的左側。漸變面板顯示紅色十字,當最小化,然後恢復

當窗體重新調整大小後,它會正確顯示,但是如果最小化窗體並將其恢復,則會得到一個大紅色的X而不是漸變。

任何人都可以發現錯誤?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Drawing.Drawing2D; 
using System.Text; 
using System.Windows.Forms; 

public class GradientPanel : Panel 
{ 
    private Color ColorA = Color.LightBlue; 
    private Color ColorB = Color.Red; 
    private LinearGradientMode GradientFillStyle = LinearGradientMode.ForwardDiagonal; 
    private Brush gradientBrush; 

    public Color colourStart 
    { 
     get { return ColorA; } 
     set { ColorA = value; Invalidate(); } 
    } 
    public Color colourEnd 
    { 
     get { return ColorB; } 
     set { ColorB = value; Invalidate(); } 
    } 
    public LinearGradientMode colourGradientStyle 
    { 
     get { return GradientFillStyle; } 
     set { GradientFillStyle = value; Invalidate(); } 
    } 

    public GradientPanel() 
    { 
     handlerGradientChanged = new EventHandler(GradientChanged); 
     ResizeRedraw = true;   
    } 

    private EventHandler handlerGradientChanged; 

    protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e) 
    { 
     gradientBrush = new LinearGradientBrush(ClientRectangle, ColorA, ColorB, GradientFillStyle); 

     e.Graphics.FillRectangle(gradientBrush, ClientRectangle); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if (gradientBrush != null) gradientBrush.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

    protected override void OnResize(EventArgs eventargs) 
    { 
     Invalidate(); 
     //base.OnResize(eventargs); 
    } 
    protected override void OnSizeChanged(EventArgs e) 
    { 
     Invalidate(); 
     //base.OnSizeChanged(e); 
    } 
    private void GradientChanged(object sender, EventArgs e) 
    { 
     if (gradientBrush != null) gradientBrush.Dispose(); 
     gradientBrush = null; 
     Invalidate(); 
    } 

} 
+1

我會避免在OnPaintBackground處理程序中創建一個新的LinearGradientBrush。我的猜測是你可能會碰到你的GDI對象限制(你可以在任務管理器中查看),因爲我認爲你沒有正確地放置你的畫筆。將它移到構造函數中,或者在顏色和樣式屬性更改時調用的函數中(並在創建新的函數之前處理前一個函數) – musefan 2012-02-21 12:13:32

+0

@musefan感謝您的理解,我將其移至構造函數中,但現在忽略(而不是顯示黑色到紅色的水平漸變,它顯示了代碼中顯示的默認值)我如何解決這個問題,因爲我從來沒有回答過它之前 – Neo 2012-02-21 12:19:49

+1

我發佈了一個答案來解釋它更多,我希望它適合你 – musefan 2012-02-21 12:28:17

回答

2

我會避免在OnPaintBackground處理程序創建一個新的LinearGradientBrush

我的猜測是你可能會觸及你的GDI對象限制(你可以在任務管理器中檢查),因爲我認爲你沒有正確地放置你的畫筆。

移動這構造,或在當顏色和樣式屬性來更改被稱爲(並創造新的人之前前面的處置)

這裏是你可以做什麼,而一個例子功能仍然允許屬性來改變顏色等...

編輯屬性:

public Color colourStart 
{ 
    get { return ColorA; } 
    set { ColorA = value; RefershBrush(); } 
} 
public Color colourEnd 
{ 
    get { return ColorB; } 
    set { ColorB = value; RefershBrush(); } 
} 
public LinearGradientMode colourGradientStyle 
{ 
    get { return GradientFillStyle; } 
    set { GradientFillStyle = value; RefershBrush(); } 
} 

附加功能:

private void RefershBrush() 
{ 
    //I think this IF block should work with no problems, been a while working with brush 
    if(gradientBrush != null) 
    { 
     gradientBrush.Dispose(); 
    } 

    gradientBrush = new LinearGradientBrush(ClientRectangle, ColorA, ColorB, GradientFillStyle); 
    Invalidate(); 
} 
+1

非常感謝musefan工作的一種享受! – Neo 2012-02-21 12:32:53

+1

@Neo,這可能是值得一讀的fi你有機會:http://www.codeproject.com/Articles/165443/Disposing-GDI-Objects-in-C-NET ...雖然它沒有真正得到讀者的好評,但它確實詳細描述了我對今天看到的東西所帶來的痛苦,我認爲在那裏有一些有用的東西需要了解。加上你可以閱讀其他讀者的任何建議的意見 – musefan 2012-02-21 12:36:48

1

它看起來並不像你正在處理刷子。

重構的代碼:

public class GradientPanel : Panel { 
    private Color ColorA = Color.LightBlue; 
    private Color ColorB = Color.Red; 
    private LinearGradientMode GradientFillStyle = LinearGradientMode.ForwardDiagonal; 

    public GradientPanel() { 
    DoubleBuffered = true; 
    ResizeRedraw = true; 
    } 

    public Color colourStart { 
    get { return ColorA; } 
    set { ColorA = value; Invalidate(); } 
    } 

    public Color colourEnd { 
    get { return ColorB; } 
    set { ColorB = value; Invalidate(); } 
    } 

    public LinearGradientMode colourGradientStyle { 
    get { return GradientFillStyle; } 
    set { GradientFillStyle = value; Invalidate(); } 
    } 

    protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e) { 
    using (var gradientBrush = new LinearGradientBrush(ClientRectangle, ColorA, ColorB, GradientFillStyle)) { 
     e.Graphics.FillRectangle(gradientBrush, ClientRectangle); 
    } 
    } 
} 

您不必在每次調整或SizeChanged將失效,因爲你已經有了一個ResizeRedraw=True屬性設置的控制。我還添加了DoubleBuffered=True屬性以控制閃爍。

我把你的漸變畫筆放在Using()塊中,這樣它就會被丟棄。

+0

我試過你的方法,仍然想出了紅十字會,但+1的雙緩衝和使用:) – Neo 2012-02-21 12:57:20

+0

@Neo你很可能用盡其他地方的資源。確保在顯示的任何其他控件或窗體中正確處理了對象。打開任務管理器並在進程下,顯示「GDI對象」列,並在運行程序時觀察exe文件的值,特別是在最小化和恢復時。如果這個數字繼續上升,就是在泄漏資源。 – LarsTech 2012-02-21 13:24:46

4

我正在做類似的事情,但即使清理了LinearGradientBrush也沒有爲我解決它。看着控制檯輸出,我注意到「在System.Drawing.dll中發生了System.ArgumentException類型的第一次機會異常。」我相信這是因爲當組件最小化時ClientRectangle是0,0。添加此代碼似乎爲我修復:

protected override void OnPaintBackground(PaintEventArgs e) 
    { 
    base.OnPaintBackground(e); 
    if (this.gradientBrush != null) 
     this.gradientBrush.Dispose(); 
    if (this.ClientRectangle.Width > 0 && this.ClientRectangle.Height > 0) 
    { 
     this.gradientBrush = new LinearGradientBrush(this.ClientRectangle, 
      FROM_GRADIENT_COLOR, TO_GRADIENT_COLOR, LinearGradientMode.Horizontal); 

     e.Graphics.FillRectangle(this.gradientBrush, this.ClientRectangle); 
    } 
    } 
相關問題