简体   繁体   中英

C# Better way to scroll custom graphic to reduce flickering

I am busy developing an C# win form application, that draws a graphical representation of a database structure in a hierarchical structure.

Everything is working fine, I just have a problem with scrolling. It has a bad flickering problem.

I have researched the following:

C# graphics flickering

Call Invalidate() when you want to refresh the surface (has helped a lot but still a little of a lag)

Also to set DoubleBuffered property to True (Problem with this I get an ArgumentException thrown with message "Parameter is not valid.". But I can set DoubleBuffered to true on my main form)

Detail on my design

I have two class Node and Link they both have GraphicsPath members, and they both have a public void Draw(Graphics g) method to draw themselves.

I also have a user control call StructureMap that has overridden the protected override void OnPaint(PaintEventArgs e) method, to loop through every Node calling it's draw function. The looping is simple because the Parent Node is link to the children nodes by a Link object. All I have to do is call the parent node's draw method, and all its children nodes are also redrawn.

I am also preforming Hit testing the same way.

Is there maybe a better way? Why can't I have DoubleBuffered set to true on my user control?

PS: This is my first post, let me know how I did?

The DoubleBuffered ArgumentException is probably caused due to the fact that you somewhere dispose the graphics object.

Also refer to this article; What could cause Double Buffering to kill my app?

Your flickering sound like it is caused by the amount of processing you have to do to draw the image.

One way to alleviate this is to draw your model to an offscreen bitmap, then your paint/scroll etc just draw that bitmap to the screen.

Then only update the bitmap if your model changes.

Using bitmap as a background image will reduce flickering. Maybe like this :

 private Bitmap _backBuffer;
 private void Form1_Paint(object sender, PaintEventArgs e)
 {
      if (_backBuffer == null)
        {
            _backBuffer = new Bitmap(Form1.Width, Form1.Height, PixelFormat.Format32bppRgb);
        }
        Graphics g = Graphics.FromImage(_backBuffer);

        g.SmoothingMode = SmoothingMode.HighQuality;

        drawSomething(g);

        //Copy the back buffer to the screen
        e.Graphics.DrawImageUnscaled(_backBuffer, 0, 0);
        Form1.BackgroundImage = _backBuffer;
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM