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

Posted on 2006-04-06
Last Modified: 2011-09-20
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.

Question by:AGBrown
    LVL 9

    Accepted Solution

    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.
    LVL 52

    Assisted Solution

    by:Carl Tawn
    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:

    LVL 2

    Expert Comment

    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.
    LVL 12

    Author Comment

    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;
    LVL 12

    Author Comment

    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.

    LVL 12

    Author Comment

    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?


    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    What Is Threat Intelligence?

    Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

    Article by: Najam
    Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
    This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
    In this sixth video of the Xpdf series, we discuss and demonstrate the PDFtoPNG utility, which converts a multi-page PDF file to separate color, grayscale, or monochrome PNG files, creating one PNG file for each page in the PDF. It does this via a c…
    This video discusses moving either the default database or any database to a new volume.

    779 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    15 Experts available now in Live!

    Get 1:1 Help Now