0

I have a panel I draw on, and I'm doing it in the paint event. I want to delete previous changes before drawing, but If I use Invalidate() or Refresh() it is redrawing it forever (it is flickering), and the strange thing is I call Invalidate() before any drawing, so if it's just forcing panel paint I shouldn't see the drawing

Edit: I figured out this:

        void _paint(object sender, PaintEventArgs e)
    {
        Panel P = (Panel)sender;
        if (painted = false) { painted = true; P.Invalidate(); }


        Shows(30);
        painted = false;
    }

It stopped flickering. Anyway, turns out I've never needed that, it is repainting the panel even without the Invalidation. But strangely when I hide only part of the panel(either with form resizing or dragging window over the panel),when becoming visible again it is painted, not repainted(I can tell because the anti-aliasing becomes solid color, producing shitty result), that's why I thought I need to Invalidate the panel. Invalidating won't stop it from happening. I think probably another event is triggered, not paint.

  • 2
    The Panel class is not ideal for this. Meant to be a container control, it doesn't use double-buffering. Use PictureBox or, if scrolling is important, your own [double-buffered panel](http://stackoverflow.com/a/3113515/17034). – Hans Passant Mar 30 '15 at 10:02
  • Can you show us your code for better analysis of the problem ? One thing I can tell you is, that when you use Refresh() you do not need to call Invalidate() because Refresh() first calls Invalidate() and then Update() right afterwards. Also Refresh() will trigger the OnPaint() event which will trigger the Paint() event so if you have your Refresh() call inside of OnPaint() or Paint() it will call itself over and over again which will cause flickering. Not sure if these informations are helpful, as I said with some code we might be able to help. – Paul Weiland Mar 30 '15 at 10:18

2 Answers2

0

I encountered a problem with my control flickering when I called Invalidate with a program I created not too long ago. I found overriding the OnPaintBackGround did the trick, it may work for you too;

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        /* Override to stop the background being repainted -> this stops flashing of the text */
    }
horHAY
  • 788
  • 2
  • 10
  • 23
0

First if all, the following condition is lacking an = sign:

if (painted = false) { painted = true; P.Invalidate(); }

It should read

if (painted == false) { painted = true; P.Invalidate(); }

or

if (!painted) { painted = true; P.Invalidate(); }

Secondly, double buffering is in many cases a good idea. To do so, paint all the content into an off-screen bitmap that has the same size as the client area of your control and then draw that bitmap to the target control if needed. Do not draw the off-screen bitmap in the OnPaint event, but whenever the content to be drawn changes!

Example:

private void PaintOffscreen()
{
    // Do whatever necessary to draw the offscreen bitmap
    ...

    // Cause the control to repaint itself. Change OnPaint to draw the bitmap only
    Invalidate();
}

void _paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawImage(offscreenBitmap, 0, 0);
}

Also, override the OnPaintBackground method as suggested by HorHAY to prevent the control from clearing the background before painting itself.

Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139