I'm trying to make a simple paint program in C#, but it keeps flickering when I'm drawing, like I need some kind of double buffering, but I don't know how to do it.
I am drawing on a Panel
and I'm using a Bitmap
to store the graphics.
Here's my code:
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);
}
}
Normally, simply adding
this.DoubleBuffered = true;
in your code should do the trick.If it does not, add this code to your form :
You can also change it using Reflection, but there is no advantage, neither readability or speed.
You need to subclass Panel to do this, because you need to override certain things. A
Panel
like this should work:However, you don't need the functionality
Panel
adds toControl
at all, that is for it to be functioning as a container. So, in fact, you should be inheriting fromControl
unless you need subcontrols.Another improvement might be to only
Invalidate
with theRectangle
that changed. This will repaint one area and reduce drawing time. You can also pass asrcRect
toGraphics.DrawImage
, thatsrcRect
being calculated frome.ClipRectangle
, for even better performance if subclassingPanel
doesn't work for you.When painting pixel maps in the Paint event, the flickering is often caused by Windows forms because it first draws the background and then the pixel map. So the flicker is the background that becomes visible for a fraction of a second.
You can set the
Opaque
style in the panel'sControlStyle
property. That will turn of the background drawing because Windows Forms now assumes that your code will completely draw the contents of the panel.You not only should turn
DoubleBuffered
totrue
, but also usePictureBox
instead ofPanel
and draw on it. This should solve your issue :).