Niksan
Niksan

Reputation: 159

Lag between Scroll event and Paint event and maybe something inbetween

I have a simple panel on a form and I'm using AutoScrollMinSize and AutoScroll to get some scrollbars on my panel, all works OK.

I also have a Scroll event which I use to invalidate the whole panel area, as defacto it seems to only invalidate bits it needs to when scrolling left/right, up/down. In addition to this I'm using a BufferedGraphics which is the same size as the panel then does a .Render(e.Graphics) as I'm wanting for it to draw upon the whole panel as if the scroll bars didn't exist.

Now, the problem I have is there seems to be a visual keep up lag when scrolling and the contents being painted, I assume this is because there's an extra draw / setup stage somewhere that I'm not familiar with either before the Scroll event is called or between that and the Paint event being called.

If I have a invalidate panel inside the paint method you don't see the problem, but this is more to do with the paint event being called many times hiding the issue.

So the way I think I understand it is, when you scroll, something under the hood does a big rectangle blit shifting contents that already exist then calls invalidate with the rectangle of the area that needs to be filled.

If this is the case, is there anyway around this, as in inhibit this stage or some other setup I'm missing to get rid of the keep up lag?

PS: I also override the OnPaintBackground method which is an empty stub.

Upvotes: 5

Views: 2145

Answers (1)

Niksan
Niksan

Reputation: 159

Ok, to answer my own question in case it helps anyone on the rare occasion you need this. Starting from someone mentioning LockWindowUpdate led me to WM_SETREDRAW and this post, SuspendDrawing, now I have smooth scrolling with the ability to paint the full panel. By just having a Scroll event doing the following. YMMV.

    [DllImport("user32.dll")]
    private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
    private const int WM_SETREDRAW = 0xB;

    private void PanelView_Scroll(object sender, ScrollEventArgs e)
    {
        Control control = sender as Control;
        if (control!=null)
        {
            if (e.Type == ScrollEventType.ThumbTrack)
            {
                // Enable drawing
                SendMessage(control.Handle, WM_SETREDRAW, 1, 0);
                // Refresh the control 
                control.Refresh();
                // Disable drawing                            
                SendMessage(control.Handle, WM_SETREDRAW, 0, 0);
            }
            else
            {
                // Enable drawing
                SendMessage(control.Handle, WM_SETREDRAW, 1, 0);
                control.Invalidate();
            }
        }
    }

Upvotes: 5

Related Questions