Flickering

J

Jon Slaughter

I always get flicking in my test code and all graphics code I'm using. It's
random but happens about once a second. Its quite annoying cause I expected
that with double buffering enabled and the fact that I'm drawing everythign
to my own bitmap that there would be no way it could flicker. (even in a
stationary scene)


I'm sure that its a programming issue... probably having to do with locking.
I figure that if I lock the bitmap that I can draw on it without the painter
using it but maybe thats not how it works?

I also get a generic GDI+ error on the painter when closing down. I have no
clue why but again, its probably some programming issue.

Thanks,
Jon

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Threading;


namespace GDITest2
{
public partial class Form1 : System.Windows.Forms.Form
{

System.Timers.Timer painter;
System.Threading.Thread thread;
Bitmap bitmap;

Graphics FormGraphics;
Graphics BitmapGraphics;


public Form1()
{
FormGraphics = this.CreateGraphics();
//FormGraphics.SmoothingMode = SmoothingMode.HighQuality;
//FormGraphics.InterpolationMode =
InterpolationMode.HighQualityBicubic;
//FormGraphics.CompositingQuality = CompositingQuality.HighQuality;
this.TopMost = true;
this.BringToFront();
this.Show();
this.TopMost = false;
this.BringToFront();
this.Show();
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint, true);
this.ClientSize = new System.Drawing.Size(700, 700);
this.Left = (1240 - this.ClientSize.Width) / 2;
this.Top = (1024 - this.ClientSize.Height) / 2;

thread.Start();
painter.Start();
}


protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
FormGraphics = this.CreateGraphics();
bitmap = new Bitmap(this.Width, this.Height);
BitmapGraphics = Graphics.FromImage(bitmap);

ThreadStart ts = new ThreadStart(calculator);
thread = new Thread(ts);

painter = new System.Timers.Timer(1000 / 30F);
painter.Elapsed += new
System.Timers.ElapsedEventHandler(painter_Elapsed);

}



void painter_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{

lock (FormGraphics)
{
lock (bitmap)
{
try
{
FormGraphics.DrawImageUnscaled(bitmap, 0, 0);
}
catch {}
}
}
}



protected override void OnPaintBackground(PaintEventArgs e) { }
protected override void OnPaint(PaintEventArgs e) { }

protected override void OnResize(EventArgs e)
{

base.OnResize(e);
lock (FormGraphics)
{
FormGraphics.Dispose();
FormGraphics = this.CreateGraphics();
lock (bitmap)
{
lock (BitmapGraphics)
{
bitmap = new Bitmap(this.Width, this.Height);
BitmapGraphics = Graphics.FromImage(bitmap);
}
}
}
}

bool closing = false;
protected override void OnClosing(System.ComponentModel.CancelEventArgs
e)
{
base.OnClosing(e);
closing = true;
}


double t = 0;
void calculator()
{
t = 0;
double dt = 0.001;
BitmapGraphics.ScaleTransform(2F, 2F);
while (!closing)
{
t += dt;
lock (bitmap)
{
BitmapGraphics.Clear(Color.Black);

//BitmapGraphics.TranslateTransform(1, -1);
BitmapGraphics.FillRectangle(Brushes.Beige, 120, 120,
30, 30);
}
Thread.Sleep(10);
} // While
}
} // Form
} // Namespace
 
M

Morten Wennevik [C# MVP]

Hi Jon,

It is considered bad practice to draw onto the graphics object outside the paint events, and since you do it asyncronously as well I wonder what Bob Powell would say (if he doesn't read this thread, try posting in the Drawing newsgroup). You are locking the bitmaps and form and aim for a 30 frames per second drawing. I suspect the flickering is because your code cannot accomplish this all the time. Having your form doublebuffered may not help if you don't use the Paint events. Not sure on this.

Furthermore, your code could easily be accomplished by creating a bitmap for the calculator program and have Paint draw this to the screen whenever necessary (for instance by calling Invalidate()).

To get rid of the GDI+ error when closing, stop the paint timer on your closing event. You should also dispose FormGraphics before you leave.

Try dropping all references to FormGraphics or this.CreateGraphics(). Have the timer event call Invalidate() and put the drawing of the bitmap inside the Paint event (you still need to lock the bitmap or the paint will work, but with black bitmaps whenever the calculator locks it). This method does not require you to stop the painter when you close either.
 
J

Jon Slaughter

Morten Wennevik said:
Hi Jon,

It is considered bad practice to draw onto the graphics object outside the
paint events, and since you do it asyncronously as well I wonder what Bob
Powell would say (if he doesn't read this thread, try posting in the
Drawing newsgroup). You are locking the bitmaps and form and aim for a 30
frames per second drawing. I suspect the flickering is because your code
cannot accomplish this all the time. Having your form doublebuffered may
not help if you don't use the Paint events. Not sure on this.

Furthermore, your code could easily be accomplished by creating a bitmap
for the calculator program and have Paint draw this to the screen whenever
necessary (for instance by calling Invalidate()).

To get rid of the GDI+ error when closing, stop the paint timer on your
closing event. You should also dispose FormGraphics before you leave.

Try dropping all references to FormGraphics or this.CreateGraphics(). Have
the timer event call Invalidate() and put the drawing of the bitmap inside
the Paint event (you still need to lock the bitmap or the paint will work,
but with black bitmaps whenever the calculator locks it). This method
does not require you to stop the painter when you close either.


Ok, I did all this and I think its working. Basically removed all form
graphics and call invalidate inside the timer and draw in the onPaint. I
tried something like this before but it didn't work but I suppose I screwed
up somehwere. (I think I was calling refresh or something... I forgot about
invalidate ;/)

Thanks,
Jon
 
J

Jon Slaughter

Whats strange is that setting

this.DoubleBuffered = true;

on my form seems to speed up the rendering by about 10x. I still get
shearing problems but I guess I would need to sync with the vrefresh to fix
that?



Thanks again,

Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top