簡體   English   中英

雙緩沖C#

[英]Double buffering C#

我正在嘗試實現以下方法:void Ball :: DrawOn(Graphics g);

該方法應該繪制球的所有先前位置(存儲在隊列中)並最終繪制當前位置。 我不知道這是否重要,但我使用g.DillEllipse(...)打印以前的位置,使用g.FillEllipse(...)打印當前位置。

問題是,你可以想象有很多繪圖要做,因此顯示開始閃爍很多。 我曾尋找過雙緩沖的方法,但我能找到的就是這兩種方式:

1)System.Windows.Forms.Control.DoubleBuffered = true;

2)SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint,true);

在嘗試使用第一個時,我得到一個錯誤,解釋說在此方法中,由於其保護級別,屬性DoubleBuffered無法訪問。 雖然我無法想象如何使用SetStyle方法。

是否有可能將緩沖區加倍,而我擁有的所有訪問權限都是我在方法中輸入的圖形對象?

提前致謝,

編輯:我創建了以下類

namespace doubleBuffer
{
    class BufferedBall : System.Windows.Forms.Form{
        private Ball ball;
        public BufferedBall(Ball ball)
        {
            this.ball = ball;
        }

    public void DrawOn(Graphics g){
        this.DoubleBuffered = true;
        int num = 0;
        Rectangle drawArea1 = new Rectangle(5, 35, 30, 100);
        LinearGradientBrush linearBrush1 =
        new LinearGradientBrush(drawArea1, Color.Green, Color.Orange, LinearGradientMode.Horizontal);
        Rectangle drawArea2 = new Rectangle(5, 35, 30, 100);
        LinearGradientBrush linearBrush2 =
           new LinearGradientBrush(drawArea2, Color.Black, Color.Red, LinearGradientMode.Vertical);
        foreach (PointD point in ball.previousLocations)
        {
            Pen myPen1;
            if (num % 3 == 0)
                myPen1 = new Pen(Color.Yellow, 1F);
            else if (num % 3 == 1)
                myPen1 = new Pen(Color.Green, 2F);
            else
                myPen1 = new Pen(Color.Red, 3F);
            num++;
            myPen1.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
            myPen1.StartCap = System.Drawing.Drawing2D.LineCap.RoundAnchor;
            myPen1.EndCap = System.Drawing.Drawing2D.LineCap.AnchorMask;
            g.DrawEllipse(myPen1, (float)(point.X - ball.radius), (float)(point.Y + ball.radius), (float)(2 * ball.radius), (float)(2 * ball.radius));
        }
        if ((ball.Host.ElapsedTime * ball.Host.FPS * 10) % 2 == 0){
            g.FillEllipse(linearBrush1, (float)(ball.Location.X - ball.radius), (float)(ball.Location.Y + ball.radius), (float)(2 * ball.radius), (float)(2 * ball.radius));
        }else{
            g.FillEllipse(linearBrush2, (float)(ball.Location.X - ball.radius), (float)(ball.Location.Y + ball.radius), (float)(2 * ball.radius), (float)(2 * ball.radius));
        }
    }
}

}

球drawOn看起來像這樣:

new BufferedBall(this).DrawOn(g);

這是你的意思嗎? 因為它還在閃爍?

Form類具有公開為受保護的DoubleBuffered屬性。 http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx但是由於您從Form派生表單,您可以使用它。

 this.DoubleBuffered = true; 

這很好,但你必須將此語句移動到構造函數。 雙緩沖需要設置,Windows Forms必須創建一個緩沖區,必須在paint事件運行之前完成。 構造函數是理想的。

為Control-derived類設置雙緩沖樣式的簡單方法是使用反射。 見這里: http//www.csharp-examples.net/set-doublebuffered/

這將為您節省僅為設置受保護屬性而繼承控件的步驟。

每次重繪時都不需要將DoubleBuffered設置為true。 繪制完成后不會禁用它。 只需從DrawOn中刪除該行並在構造函數或Forms Designer中設置它並檢查結果。 將值設置為false會產生明顯的閃爍,而設置為true則不會。

我嘗試了一個表單,其中一個計時器強制每毫秒重繪一次,並注意到當DoubleBuffered為真時沒有閃爍:

private int yDir = 1,xDir=1;
int step = 1;

private void timer1_Tick(object sender, EventArgs e)
{
    if (ball.Location.Y >= this.Height-50)
        yDir =   -1 ;
    if (ball.Location.X >= this.Width-50) 
        xDir= -1 ;

    ball.MoveBy(xDir*step,yDir*step);
    ball.Host.ElapsedTime++;
    this.Invalidate();
 }

private void DoubleBufferedBall_Paint(object sender, PaintEventArgs e)
{                      
        DrawOn(e.Graphics);
}

我將為您拋出的另一個選項是將所有繪圖都繪制到Bitmap,然后在OnPaint方法中,只需將該Bitmap繪制到窗體中即可。

它的手冊,但它給你完全控制。 我在我的一些寵物項目中使用它取得了一些成功。

您也可能想要查看XNA - 這可能對您的項目有點過分,但您可以在WinForms中使用XNA作為渲染引擎。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM