Search code examples
c#winforms

How can i capture the screen without the Form?


This is a class i'm using to capture my screen and mouse cursour as screenshot. But i want to make somehow that if the Form is in the middle of the screen don't capture it captrue the screen and the area behind the Form but not the Form it self.

Even if the form is in the front and i click on buttons or change something in the Form while the application is running do not capture it just keep capture the screen the area behind the Form like the Form is not there.

using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace ScreenShotDemo
{
    public class ScreenCapture
    {
        [StructLayout(LayoutKind.Sequential)]
        struct CURSORINFO
        {
            public Int32 cbSize;
            public Int32 flags;
            public IntPtr hCursor;
            public POINTAPI ptScreenPos;
        }

        [StructLayout(LayoutKind.Sequential)]
        struct POINTAPI
        {
            public int x;
            public int y;
        }

        [DllImport("user32.dll")]
        static extern bool GetCursorInfo(out CURSORINFO pci);

        [DllImport("user32.dll")]
        static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon);

        const Int32 CURSOR_SHOWING = 0x00000001;

        public static Bitmap CaptureScreen(bool CaptureMouse)
        {
            Bitmap result = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);

            try
            {
                using (Graphics g = Graphics.FromImage(result))
                {
                    g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);

                    if (CaptureMouse)
                    {
                        CURSORINFO pci;
                        pci.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(CURSORINFO));

                        if (GetCursorInfo(out pci))
                        {
                            if (pci.flags == CURSOR_SHOWING)
                            {
                                DrawIcon(g.GetHdc(), pci.ptScreenPos.x, pci.ptScreenPos.y, pci.hCursor);
                                g.ReleaseHdc();
                            }
                        }
                    }
                }
            }
            catch
            {
                result = null;
            }

            return result;
        }
    }

What i mean is that i will see the Form when it's running and i will be able to change things click buttons but the captured screenshot if i will edit it with Paint i will not see the Form .

This is in Form1 how i make the capture:

private void StartRecording_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
        }

And timer1 tick event:

private void timer1_Tick(object sender, EventArgs e)
        {
            using (bitmap = (Bitmap)ScreenCapture.CaptureScreen(true))
            {
                ffmp.PushFrame(bitmap);
            }       
        }

This line make the actual capture: using (bitmap = (Bitmap)ScreenCapture.CaptureScreen(true))


Solution

  • Um.. Hide the form?

    this.Visible = false; and THEN run the screenshot method.

    Like this:

    protected Bitmap TakeScreenshot(bool cursor)
    {
       Bitmap bitmap;
       this.Visible = false;
       bitmap = CaptureScreen(cursor);
       this.Visible = true;
       return bitmap;
    }
    

    and use it in your code the way you wanted:

     private void timer1_Tick(object sender, EventArgs e)
     {
        using (bitmap = (Bitmap)ScreenCapture.TakeScreenshot(true))
        {
            ffmp.PushFrame(bitmap);
        }       
     }