C # программа рисования мерцания - PullRequest
5 голосов
/ 03 декабря 2011

Я пытаюсь создать простую программу рисования на C #, но она продолжает мерцать, когда я рисую, как будто мне нужна какая-то двойная буферизация, но я не знаю, как это сделать.

Я рисую Panel и использую Bitmap для хранения графики.

Вот мой код:

public partial class Form1 : Form
{
    private Bitmap drawing;
    private bool leftDown = false;
    private int prevX;
    private int prevY;
    private int currentX;
    private int currentY;

    public Form1()
    {
        InitializeComponent();

        drawing = new Bitmap(panel1.Width, panel1.Height);
    }

    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            leftDown = true;

            prevX = e.X;
            prevY = e.Y;
        }
    }

    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (leftDown)
        {
            Graphics g = Graphics.FromImage(drawing);

            currentX = e.X;
            currentY = e.Y;

            g.DrawLine(new Pen(Color.Black), new Point(currentX, currentY), new Point(prevX, prevY));
            panel1.Invalidate();

            prevX = currentX;
            prevY = currentY;

            g.Dispose();
        }
    }

    private void panel1_MouseUp(object sender, MouseEventArgs e)
    {
        leftDown = false;
    }

    private void panel1_MouseLeave(object sender, EventArgs e)
    {
        leftDown = false;
    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawImageUnscaled(drawing, 0, 0);
    }
}

Ответы [ 4 ]

5 голосов
/ 03 декабря 2011

Вы не только должны повернуть DoubleBuffered на true, но также использовать PictureBox вместо Panel и рисовать на нем. Это должно решить вашу проблему:).

2 голосов
/ 03 декабря 2011

Для этого вам нужно создать подкласс Panel, потому что вам нужно переопределить определенные вещи. A Panel, как это должно работать:

class DoubleBufferedPanel : Panel {
    public DoubleBufferedPanel() : base() {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint |
                      ControlStyles.DoubleBuffered |
                      ControlStyles.Opaque |
                      ControlStyles.OptimizedDoubleBuffer, true);
    }
    public override void OnPaint(PaintEventArgs e) {
        // Do your painting *here* instead, and don't call the base method.
    }

    // Override OnMouseMove, etc. here as well.
}

Однако вам не нужна функциональность, которую Panel добавляет к Control, то есть для того, чтобы она функционировала как контейнер. Так что, на самом деле, вы должны наследовать от Control, если вам не нужны субконтроли.

Еще одним улучшением может быть только Invalidate с Rectangle, который изменился. Это перекрасит одну область и сократит время рисования. Вы также можете передать srcRect в Graphics.DrawImage, при этом srcRect рассчитывается из e.ClipRectangle, для еще большей производительности, если подкласс Panel не работает для вас.

0 голосов
/ 03 декабря 2011

При рисовании карт пикселей в событии Paint, мерцание часто вызывается формами Windows, потому что сначала он рисует фон, а затем карту пикселей. Таким образом, мерцание - это фон, который становится видимым на долю секунды.

Вы можете установить стиль Opaque в свойстве ControlStyle панели. Это изменит фоновый рисунок, потому что теперь Windows Forms предполагает, что ваш код будет полностью рисовать содержимое панели.

0 голосов
/ 03 декабря 2011

Как правило, простое добавление this.DoubleBuffered = true; в коде должно помочь.

Если этого не произойдет, добавьте этот код в форму:

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;
        return cp;
    }
}

Вы также можете изменить егоиспользуя отражение, но нет никаких преимуществ, ни читаемости, ни скорости.

...