How to fix: Form that displays an animation clears the screen randomly?

I'm using GDI+ through C# in .NET 2.0 via the System.Drawing classes. I have a single form which I black out and use as a canvas to animate pixels; effectively a number of pixels are turned to a different colour using (more or less) the following code (the form is using DoubleBuffering):

  Graphics formGraphics; // class field - set from this.CreateGraphics() on initialisation
  LinearGradientBrush pointBrush1; // class field - set on initialisation
  LinearGradientBrush pointBrush2; // class field - set on initialisation
  OnTimerFire () // timer period is 1 millisecond
    Timer1.Enabled = false;
    for (int i = 0; i < iterationsPerTimerFire; i++)
      Point myPoint; // set in another method
      if (this.PaintWithBrush1)
        formGraphics.FillRectangle(pointBrush1, myPoint.X, myPoint.Y, 1, 1);
        formGraphics.FillRectangle(pointBrush2, myPoint.X, myPoint.Y, 1, 1);
    Timer1.Enabled = true;

However, periodically (and randomly in terms of the time since the last time it happened) the form goes black again, and all the pixels that were coloured in are turned back to black. This can happen after only half a second, or after two minutes or any time inbetween, and will happen repeatedly during each animation. I estimate I'm drawing about 50,000 to 100,000 pixels a second at full speed, though it also happens when it runs slower, and the length of time between "resets" doesn't seem to correlate to the number of pixels drawn.

How can I prevent this? The form is running in maximised mode, but I think I've seen the same behaviour in normal mode as well - just not recently as I've had it in maximised mode for a while now.

LVL 12
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

I don't know the reason of this phenomenon, but as I know, all drawings to the screen should be done in the OnPaint() method. In the OnTimerFire() method Refresh() should be called to force repainting.

Nevertheless you can draw into a memory bitmap anywhere in the code.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Carl TawnSystems and Integration DeveloperCommented:
Its probably due to a Paint message being sent to your window. As pallosp said, you should really do all your drawing in the paint method. However, refreshes of the window can happen outside of the Paint event, you can prevent that by adding the following line to your forms constructor:

What kind of timer are you using? Are you using a System.Windows.Forms.Timer or a System.Timers.Timer? Perhaps this could be a threading issue?. But I agree with pallosp, you should update the UI on the paint method.
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

AGBrownAuthor Commented:
I'll try moving the paints to the paint event and see what happens. carl_tawn, I've actually got this at the top of my initialisation (sorry I didn't put it in to start with):
    this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
    DoubleBuffered = true;
AGBrownAuthor Commented:
Just to let you know, I'm still struggling with trying to work out if this has worked or not. Hope to get back to you all soon.

AGBrownAuthor Commented:
I've revived this project and I just spent an afternoon looking through it. The problem I've experienced is so intermittent that it's hard to tell if any one thing makes a difference.

For the people who have helped out; it would seem that moving the code I initially posted into a method, and calling that from OnPaint by making the timer Elapsed event call this.Refresh() did help. Interestingly I also realised that I was painting the form black in the Constructor for the form. Removing that altogether and keeping the method call to my first-post code in OnPaint does seem to have removed the problem.

So I now have a form without a background. The idea of this project was to help me get to grips with painting graphics on screen; unfortunately it seems to have left me with more questions than answers at the moment! I _think_ that we may have solved the problem, but I don't know enough to say if we have or not.

I would like to award points to pallosp (for pointing out the OnPaint idea) and carl_tawn (for confirming that I was right to put in my this.SetStyle call); does that seem reasonable?

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.