1

I wrote a program that draws a specific situation of a board game(I think it's called "Ludo" in English). Now I can draw all the fields and the pawns etc., but if a pawn is moved I have to redraw that pawn. The problem is that the screen flashes for a very short time when I do this. This is probably because I first clear all fields and pawns, and then redraw them(I'm going to improve this, but the problem will, in smaller form, still occur I think), the screen is then flashing between the time I cleared everything until I redrawed everything. Is there a way to tell C# not to redraw even when I specifically call something like this.Controls.Clear() until I tell it to?

I already tried it with this.SuspendLayout(), because the name suggests it should do exactly this, but that doesn't work.

teuneboon
  • 4,034
  • 5
  • 23
  • 28
  • 2
    Just tried this.DoubleBuffered = true; It does reduce the flicker, but it's still not gone – teuneboon Mar 28 '11 at 20:59
  • There are more more specific Buffering options described here, it was very useful for my chart drawing project. Click: http://www.codeproject.com/KB/graphics/DoubleBuffering.aspx – thmshd Mar 28 '11 at 21:03
  • If the .NET double buffering implementation doesn't work for you, you should try implementing your own buffering mechanism by caching your draws to a bitmap, and then render the entire bitmap. You're experiencing screen tear because you're essentially forcing your display device to refresh multiple parts of the screen in rapid succession. You want to minimize the number of draw requests to the display. – Chris Hutchinson Mar 28 '11 at 21:04
  • This might be of use: http://stackoverflow.com/questions/615781/can-i-suspend-redrawing-of-a-form-until-i-have-performed-all-updates – Jim Mischel Mar 28 '11 at 21:07

4 Answers4

4

Flickering is always going to be somewhat of a problem in Winforms custom graphics.

Try this: Instead of drawing the pawn's positions on the Form somewhere, draw them onto a Bitmap. When it's all done, simply change the Image of a PictureBox on your form to be the Bitmap. The form will be redrawn using the new Image. You can use two Bitmap objects (which are admittedly quite large) and clean them each time to avoid the program being a memory hog. Voila, you now have "page-flipping" graphics, which can be drawn and displayed independently of other requests to redraw the form.

KeithS
  • 70,210
  • 21
  • 112
  • 164
  • Great idea, I'll try this. Have to wait a couple of minutes before I can accept this as an answer though. – teuneboon Mar 28 '11 at 21:06
0

When you tell it to clear everything and then redraw it, it will flash like that. But how come when you move a pawn you don't draw it in the new space and draw a blank over top of where it used to be. This will move the pawn without refreshing the whole screen or clearing everything.

Also I think the game you are talking about is Chess. Thats the only game I know with Pawns, and I've never heard of Ludo. :P

Loogawa
  • 389
  • 6
  • 24
  • 1
    There's this crazy thing now called The Internet, and turns out it's great for finding out about things [you've never heard of](http://en.wikipedia.org/wiki/Ludo_%28board_game%29). :) – Dan J Mar 28 '11 at 21:02
  • 1
    :( That looks like the battle level from Mario Kart 64 though. Yea I know off topic but it had to be said – Loogawa Mar 28 '11 at 21:04
  • I'm actually Dutch, quite a well known game here, although it's called "Mens Erger Je Niet" here ^^ – teuneboon Mar 28 '11 at 21:06
  • @sehe no, ludo is not the Italian for game :) – Felice Pollano Mar 28 '11 at 21:07
  • Ok my bad it must be in latin then. @teuneboon: Mens Erger Je Niet explained it for me – sehe Mar 28 '11 at 21:13
0

Best solution is the one of KeithS, but a faster option could be: have two images for each part, one on the white and one on the black, plus both empty square. In the move place the proper empty square in the leaving square, and the proper part on gthe destination square. This is a zero flicker, old ages ( so fast ) approach :)

Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
0

Although @KeightS's solution is nice, I'd much rather solve it by being able to suspend/resume drawing all together:

public partial class Form1 : Form
{
    private bool suspendDraw;

    public Form1()
    {
        this.InitializeComponent();
    }

    public void SuspendDraw()
    {
        this.suspendDraw = true;
    }

    public void ResumeDraw()
    {
        this.suspendDraw = false;
    }

    private const int WM_PAINT = 0x000F;

    protected override void WndProc(ref Message m)
    {
        if ((m.Msg != WM_PAINT) || (!this.suspendDraw && m.Msg == WM_PAINT))
        {
            base.WndProc(ref m);
        }
    }

}

You just need to call the SuspendDraw/ResumeDraw() methods to control allowing painting.

TheCloudlessSky
  • 18,608
  • 15
  • 75
  • 116
  • Although this does decrease flicker even more than the doublebuffer, it still gives a tiny, tiny bit of flicker, I might always have some flicker, but then I'd rather use a less "hacky" solution like KeithS's, thanks for the answer though – teuneboon Mar 28 '11 at 21:14
  • @teuneboon - Is `DoubleBuffering` turned on with this method because it should be true when using this method. KeithS's solution *is* double buffering...which is already built into .NET. If you're worried about "hacky" solutions like this, don't use GDI+ for graphics as it's not hardware accelerated! – TheCloudlessSky Mar 28 '11 at 21:16