Click here to Skip to main content
15,890,282 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, I am trying to draw a checkerboard pattern onto my windows form. I am using the following code but it means that whenever the window gets repainted (e.g. hover over a button) it causes the pattern to be redrawn and flicker. Is there a better way to achieve this?

The code to draw the checkerboard is:
private void drawBoard(Graphics g) {
    bool dark = true;
    for (int i = 0; i < 8; i++) {
        dark = !dark;
        for (int j = 0; j < 8; j++) {
            dark = !dark;

            Pen blackPen = new Pen(Color.Black, 2);
            SolidBrush brush;
            if (dark) {
                brush = new SolidBrush(Color.LightGray);
            } else {
                brush = new SolidBrush(Color.Gray);
            }

            int x = 50 * i + 10;
            int y = 50 * j + 10;
            int width = 50;
            int height = 50;
            // Draw rectangle to screen.
            g.DrawRectangle(blackPen, x, y, width, height);
            g.FillRectangle(brush, x, y, width, height);
        }
    }
} 


The main form just calls this function when the Paint event handler is called.
Posted

All correct. Consider using Control.DoubleBuffered, assign it to true — usual effective tool to overcome flickering. To do that, you need to create your own control for drawing, because this member is protected:

C#
internal class MyControl : Control {
    internal MyControl() { DoubleBuffered = true; }
    //...
}


Also, something not related to flicker, but helpful to improve performance: when you change something in graphics, to trigger control's Paint event you will need to call Control.Invalidate. Instead of usual parameter-less Invalidate use Invalidate with parameters, which allows you to invalidate only a modified part of the scene.

[EDIT]
Do yourself a favor, use custom Control for painting (sub-classed as I show above), not Form. With Form you loose bit chunk of flexibility.

—SA
 
Share this answer
 
v3
Comments
JOAT-MON 7-Feb-11 23:36pm    
Just one thing, he is painting from form: Form.DoubleBuffered is public. (+5 agree with advice)
Sergey Alexandrovich Kryukov 8-Feb-11 1:09am    
Sorry, it is not:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx says:
protected virtual bool DoubleBuffered { get; set; }
Also, I test my codelets as I answer, compile it, etc.
JOAT-MON 8-Feb-11 5:03am    
Understood, the point I was making is that he is not drawing from the Control class, but rather from the Form class. The Control.DoubleBuffered is protected virtual, and the Form class implements it as a public property: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.aspx

I felt it was relevant because Form class is the level at which the OP is drawing, meaning it is not necessary to create your own control...the DoubleBuffered is already publicly implemented for this class.
Sergey Alexandrovich Kryukov 8-Feb-11 18:44pm    
Oh, good point. It should better be Control, not Form.
Thank you for the note.
--SA
Henry Minute 8-Feb-11 19:00pm    
Even for Control, it is possible.

Take a look at SetStyle http://msdn.microsoft.com/en-us/library/system.windows.forms.control.setstyle%28v=VS.90%29.aspx.

This doesn't invalidate your answer though.
While I like SAKryukovs' solution, another option is to use a bitmap - paint 4 of your squares using your favourite paint program, and use the bitmap as the BackgroundImage[^] for the form. Set BackgroundImageLayout[^] to ImageLayout.Tile[^].

This way you can have your checkboard pattern without writing a single line of code, and still avoid the flickering :)

Now, if you want to take this further you can always draw the complete checkboard pattern to a Bitmap using System.Drawing - or use a drawing package to create an enhanced metafile containing your checkboard pattern - this will scale pretty well too.


Regards
Espen Harlinn
 
Share this answer
 
v2
Comments
JOAT-MON 8-Feb-11 17:28pm    
+4 Utilizing a bitmap is a valid alternative, but if you look at the OP's code, he is trying to create an 8 X 8 board, not just the pattern as a background. For the OP's scenario, he would need to have a bitmap that was his full board(8 X 8) and ImageLayout not set to Tile.
Espen Harlinn 8-Feb-11 17:36pm    
As I mentioned, I like SAKryukovs' solution - using the BackgroundImage property, the way I mentions is just a simple alternative. Now, if he wanted to take it further he can always draw his complete checkboard pattern to a Bitmap using System.Drawing - or he could use a drawing package to create an enhanced metafile containing his checkboard pattern.

I just wanted to draw attention to the BackgroundImage property - there are numerous ways this can be used to accomplish his task :)
JOAT-MON 8-Feb-11 17:43pm    
So true. We could probably create a rather big page full of alternatives to accomplish that. :)
JF2015 10-Feb-11 1:15am    
Good alternative. 5+
Espen Harlinn 10-Feb-11 15:34pm    
Thank you JF2015!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900