[英]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.