Question

I've a Panel which fills the parent Form.
And I used a Timer to capture screen ,
and set the screenshot as background image of Panel periodically.

However, it runs into crazy flickering. What can I do to solve it?

//Part of code
 public partial class Form1 : Form
    {

        DxScreenCapture sc = new DxScreenCapture();

        public Form1()
        {
            InitializeComponent();

            panelMain.BackgroundImageLayout = ImageLayout.Zoom;
         }

        private void Form1_Load(object sender, EventArgs e)
        {
        }



        void RefreshScreen()
        {
            Surface s = sc.CaptureScreen();

            DataStream ds = Surface.ToStream(s, ImageFileFormat.Bmp);
            panelMain.BackgroundImage = Image.FromStream(ds);

            s.Dispose();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            RefreshScreen();

        }
    }
Was it helpful?

Solution

Try using a double buffered panel. Inherit panel, set DoubleBuffered to true and use that panel instead of default panel:

    namespace XXX
    {
        /// <summary>
        /// A panel which redraws its surface using a secondary buffer to reduce or prevent flicker.
        /// </summary>
        public class PanelDoubleBuffered : System.Windows.Forms.Panel
        {
            public PanelDoubleBuffered()
                : base()
            {
                this.DoubleBuffered = true;
            }
        }
    }

EDIT

Additionally I want to encourage you to take care a little more about the resources you use. Whenever an object implements the IDisposable interface - dispose the object when not needed any more. This is very important when dealing with unmanaged resources, such as streams!

    void RefreshScreen()
    {
            using (Surface s = sc.CaptureScreen())
            {
                using (DataStream ds = Surface.ToStream(s, ImageFileFormat.Bmp))
                {
                    Image oldBgImage = panelMain.BackgroundImage;
                    panelMain.BackgroundImage = Image.FromStream(ds);
                    if (oldBgImage != null)
                        oldBgImage.Dispose();
                }
            }
    }

OTHER TIPS

There is actually an easier solution in Visual Studio that requires no code!

If you go to Solution Explorer and then double click on your form (Form1) there will be a list that pops up (If it does not pop up you just have to right click on your form and go to Properties and double click again). Then, go to DoubleBuffered and change it to True.

I found the answer by myself from other site. It sets some ControlStyles on the panel like the following code. And no flickering any more.

class SomePanel : Panel
{
    public SomePanel()
    {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.SetStyle(ControlStyles.UserPaint, true);
    }
}

This is worked for me , Try this

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams handleParms = base.CreateParams;
                handleParms.ExStyle |= 0x02000000;
                return handleParms;
            }
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top