Двойная буферизация C#

Я пытаюсь реализовать следующий метод: пустой Ball:: DrawOn (Графика g);

Метод должен потянуть все предыдущие местоположения (сохраненный в очереди) шара и наконец текущего местоположения. Я не знаю, имеет ли это значение, но я печатаю предыдущие местоположения с помощью g. DrawEllipse (...) и текущее местоположение с помощью g. FillEllipse (...).

Вопрос, что, как Вы могли предположить, существует много рисования, которое будет сделано, и таким образом дисплей начинает мерцать очень. Я искал путь к двойному буферу, но все, что я мог найти, является этими 2 путями:

1) Система. Windows. Формы. Управление. DoubleBuffered = верный;

2) SetStyle (ControlStyles. DoubleBuffer | ControlStyles. UserPaint | ControlStyles. AllPaintingInWmPaint, верный);

при попытке использовать первое, я получаю ошибку при объяснении, что от в этом методе Свойство 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);

Это то, что Вы имели в виду? потому что это все еще мерцает?

5
задан LmSNe 18 June 2010 в 14:36
поделиться

5 ответов

Класс формы имеет свойство DoubleBuffered как защищенное. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx , но поскольку вы получаете свою форму из Form , вы можете использовать Это.

3
ответ дан 14 December 2019 в 01:01
поделиться

Более простой способ установить стиль для двойной буферизации классов, производных от Control, - использовать отражение. См. здесь: http://www.csharp-examples.net/set-doublebuffered/

Это избавит вас от необходимости создавать подкласс элемента управления только для установки защищенного свойства.

2
ответ дан 14 December 2019 в 01:01
поделиться

Другой вариант, который я вам предложу, это сделать все рисунки в Bitmap, а затем в методе OnPaint просто нарисовать этот Bitmap на форме.

Это ручная работа, но она дает вам полный контроль. Я использовал его с некоторым успехом в некоторых своих домашних проектах.

Вы также можете посмотреть на XNA - это может быть излишним для вашего проекта, но вы можете использовать XNA в WinForms в качестве движка рендеринга.

0
ответ дан 14 December 2019 в 01:01
поделиться

Вам не нужно устанавливать DoubleBuffered в true каждый раз при перерисовке. Она не отключается при завершении рисования. Просто удалите строку из DrawOn и установите ее в конструкторе или Forms Designer и проверьте результаты. Установка значения false приводит к значительному мерцанию, а установка true - нет.

Я попробовал ваш код в форме, где таймер заставляет перерисовывать изображение каждую миллисекунду, и заметил отсутствие мерцания, когда DoubleBuffered равно true:

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);
}
1
ответ дан 14 December 2019 в 01:01
поделиться
это. DoubleBuffered = true;

Это нормально, но вы должны переместить этот оператор в конструктор. Двойная буферизация требует настройки, Windows Forms должна создать буфер, что должно быть сделано до запуска события paint. Конструктор идеален.

3
ответ дан 14 December 2019 в 01:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: