Daniel Voit
Daniel Voit

Reputation: 111

Why i'm getting parameter is not valid after some seconds when feeding a pictureBox with images?

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
                try
                {
                    for (int i = 0; i < 1000; i++)
                    {
                        System.Threading.Thread.Sleep(500);
                        if (pictureBox1.Image != null)
                            pictureBox1.Image.Dispose();
                        pictureBox1.Image = sc.CaptureWindowToMemory(windowHandle);
                    }
                }
                catch(Exception err)
                {
                    string error = err.ToString();
                }
        }

And

public Bitmap CaptureWindowToMemory(IntPtr handle)
        {
            Image img = CaptureWindow(handle);
            Bitmap bmp = new Bitmap(img);
            bmp.Save("foo.png", System.Drawing.Imaging.ImageFormat.Png);
            return bmp;
        }

And

public Image CaptureWindow(IntPtr handle)
        {
            // get te hDC of the target window
            IntPtr hdcSrc = User32.GetWindowDC(handle);
            // get the size
            User32.RECT windowRect = new User32.RECT();
            User32.GetWindowRect(handle, ref windowRect);
            int width = windowRect.right - windowRect.left;
            int height = windowRect.bottom - windowRect.top;
            // create a device context we can copy to
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            // create a bitmap we can copy it to,
            // using GetDeviceCaps to get the width/height
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
            // select the bitmap object
            IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
            // bitblt over
            GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
            // restore selection
            GDI32.SelectObject(hdcDest, hOld);
            // clean up 
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);
            // get a .NET image object for it
            Image img = Image.FromHbitmap(hBitmap);
            // free up the Bitmap object
            GDI32.DeleteObject(hBitmap);
            return img;
        }

If I set the thread to sleep for 5000ms it will work but will be too slow to display the images. When set it to 500ms or lower like 50ms then after 20-25 seconds i'm getting exception parameter is not valid in Program.cs on

Application.Run(new Form1());

Upvotes: 0

Views: 159

Answers (1)

Blorgbeard
Blorgbeard

Reputation: 103447

You need to dispatch to the UI thread when you access a control that was created by it.

pictureBox1.Invoke(new Action(() => {
    if (pictureBox1.Image != null)
        pictureBox1.Image.Dispose();
    pictureBox1.Image = sc.CaptureWindowToMemory(windowHandle);
}));

It seems like you could simply be using a System.Windows.Forms.Timer in place of your background worker, if this is all it's doing.

Upvotes: 1

Related Questions