Skip to main content

Flicker free Drawing with WinForm in C#

Just create a C# WinForm Project,

Name the form "FormMain" and add a button "buttonRun".

Use the code below then you can test it.


Main idea is:

Draw some image on a bitmap first, then "paste" the bitmap on the graphics of the form.

This will reduce the "flicking" of the window.


Code: ==================================
public partial class FormMain : Form
{
    bool isDrawing = false;
    Bitmap gBmp = null;
    Graphics gGraphImg = null;

    // this variables are just for the Curve
    int gX = 350, gY = 200;
    int offX = 180, offY = 100;

    public FormMain()
    {
        InitializeComponent();

        CreateBitmapAndGraphic();
    }

    // gBmp & gGraph will be created, when the form is initialized or resized.
    private void CreateBitmapAndGraphic()
    {
        if (gBmp != null)
        {
            gBmp.Dispose(); // Dispose it to prevent memory usage too high, when redraw too many times.
        }
        gBmp = new Bitmap(this.Width, this.Height);

        if (gGraphImg != null)
        {
            gGraphImg.Dispose(); // Dispose it to prevent memory usage too high, when redraw too many times.
        }
        gGraphImg = Graphics.FromImage(gBmp);
    }

    // Draw two images in a bitmap
    private Bitmap DrawCurveInBitmap()
    {
        // gBmp & gGraph will be created, when the form is initialized or resized.

        gGraphImg.Clear(this.BackColor);

        // Draw Image 1 =======================================
        Rectangle rectangle = new Rectangle(50, 100, 150, 150);

        gGraphImg.DrawRectangle(System.Drawing.Pens.Red, rectangle);
        gGraphImg.DrawEllipse(System.Drawing.Pens.Black, rectangle);

        // Draw Image 2 =======================================
        // Create pens.
        Pen orangePen = new Pen(Color.Orange, 2);
        Pen greenPen = new Pen(Color.Green, 3);

        // Create points that define curve.
        //    the point6 will be moved by the mouse!
        Point point1 = new Point(50 + offX, 50 + offY);
        Point point2 = new Point(100 + offX, 25 + offY);
        Point point3 = new Point(200 + offX, 5 + offY);
        Point point4 = new Point(250 + offX, 50 + offY);
        Point point5 = new Point(300 + offX, 100 + offY);
        //Point point6 = new Point(350 + offX, 200 + offY);
        Point point6 = new Point(gX + offX, gY + offY);
        Point point7 = new Point(250 + offX, 250 + offY);
        Point[] curvePoints = { point1, point2, point3, point4, point5, point6, point7 };

        // Draw lines between original points to screen.
        gGraphImg.DrawLines(orangePen, curvePoints);
        // Draw curve to screen.
        gGraphImg.DrawCurve(greenPen, curvePoints);

        return gBmp;
    }

    // The Draw function, which will be called by event functions.
    private void DrawImages()
    {
        Graphics graphics = this.CreateGraphics(); // when resized, the graphics must renew, so, create it each time

        // to make it flicker-free
        // 1. draw the image in a bitmap, which is done in the function DrawCurveInBitmap
        // 2. then draw the bitmap on the graphics of the form once.
        graphics.DrawImage(DrawCurveInBitmap(), 0, 0);

        // graphics.Dispose(); // Dispose it to prevent memory usage too high. After test, it's not necessary.
    }

    // click the buttonRun to set the point6 to a constant position
    private void buttonRun_Click(object sender, EventArgs e)
    {
        // set point6 to a posistion
        gX = 350;
        gY = 200;

        DrawImages();
    }

    // form resize and redraw
    private void FormMain_Resize(object sender, EventArgs e)
    {
        CreateBitmapAndGraphic();

        DrawImages();
    }

    // mouse click and redraw, point6 will be set to the tip of mouse
    private void FormMain_MouseDown(object sender, MouseEventArgs e)
    {
        isDrawing = true;

        gX = e.X - offX;
        gY = e.Y - offY;

        DrawImages();
    }

    // mouse down and move will redraw, point6 will follow the mouse's movement
    private void FormMain_MouseMove(object sender, MouseEventArgs e)
    {
        if (isDrawing)
        {
            gX = e.X - offX;
            gY = e.Y - offY;

            DrawImages();
        }
    }

    // toggle the mouse off.
    private void FormMain_MouseUp(object sender, MouseEventArgs e)
    {
        isDrawing = false;
    }
}

Comments