My objective is to move visual elements drawn using methods of a Graphics object across a Form with no flicker or artifacting (in .NET 3.5). I can successfully achieve flickerless movement by either using automatic double buffering (setting the Form's DoubleBuffered property to true) or implementing a back-buffer myself. I am however struggling to find a way to use either method without clearly visible artifacts showing.
When using automatic double buffering, a page-tearing effect is evident. It looks as though the back-buffer is being slowly, progressively copied to the form, from top to bottom, over as many as three refreshes of my 60Hz LCD.
When I implement double buffering myself (see code block for details) it looks as though the back buffer is copied to the form fast enough for no page-tearing to occur. However another type of artifact sometimes appears. The code below, which allows you to move a blue rectangle on a white background left and right on the form using the arrow keys, should reproduce the effect as a series of horizontal white bands that sometimes appear on the left and right edges of the rectangle just as it is moved.
public partial class Form1 : Form {
int x;
Bitmap buffer;
public Form1() {
InitializeComponent();
buffer = new Bitmap(Width, Height);
}
private void Form1_Paint(object sender, PaintEventArgs e) {
Graphics g = Graphics.FromImage(buffer);
g.Clear(Color.FromArgb(255, 255, 255));
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.FillRectangle(Brushes.Blue, x, 0, 100, 500);
e.Graphics.DrawImageUnscaled(buffer, 0, 0);
}
protected override void OnPaintBackground(PaintEventArgs pevent) {
//Don't allow the background to paint
}
private void Form1_KeyDown(object sender, KeyEventArgs e) {
const int scrollSpeed = 20;
if(e.KeyData == Keys.Left) {
x -= scrollSpeed;
Refresh();
}
else {
if(e.KeyData == Keys.Right) {
x += scrollSpeed;
Refresh();
}
}
}
}
if(others able to reproduce the effect) {
Am I doing something wrong, perhaps triggering some
kind of race condition in the painting code or is
this just a behavior of the runtime that I have to
live with?
}
else {
Could it be a peculiarity of my display card or a
bugged display driver?
}