/// <summary>
        /// Creates an Image object containing a screen shot of a specific window
        /// </summary>
        /// <param name="handle">The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
        /// <returns></returns>
        private Image CaptureWindow(IntPtr handle)
        {
            // get te hDC of the target window
            IntPtr hdcSrc = User32.GetWindowDC(handle);
            // get the size
            Rectangle rect = new Rectangle();

            User32.GetWindowRect(handle, out rect);
            int width  = rect.Width - rect.X;
            int height = rect.Height - rect.Y;

            // create a bitmap we can copy it to,
            // using GetDeviceCaps to get the width/height
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
            // create a device context we can copy to
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            // select the bitmap object
            IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);

            // bitblt over
            GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
            //Print window
            User32.PrintWindow(handle, hdcDest, 0);

            // restore selection
            GDI32.SelectObject(hdcDest, hOld);

            // get a .NET image object for it
            Image img = Image.FromHbitmap(hBitmap);

            // free up the Bitmap object
            GDI32.DeleteObject(hBitmap);
            // clean up
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);

            return(img);
        }
Example #2
0
        public Image CaptureWindow(IntPtr handle)
        {
            IntPtr hdcSrc = User32.GetWindowDC(handle);

            User32.Rect windowRect = new User32.Rect();
            User32.GetWindowRect(handle, ref windowRect);
            int    width   = windowRect.right - windowRect.left;
            int    height  = windowRect.bottom - windowRect.top;
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
            IntPtr hOld    = GDI32.SelectObject(hdcDest, hBitmap);

            GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.Srccopy);
            GDI32.SelectObject(hdcDest, hOld);
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);

            Image img = Image.FromHbitmap(hBitmap);

            GDI32.DeleteObject(hBitmap);

            return(img);
        }
Example #3
0
        /// <summary>
        /// Creates an Image object containing a screen shot of a specific window
        /// </summary>
        /// <param name="handle">The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
        /// <returns></returns>
        public Image CaptureWindow(IntPtr handle)
        {
            IntPtr hdcSrc = User32.GetWindowDC(handle);

            User32.RECT windowRect = new User32.RECT();
            User32.GetWindowRect(handle, ref windowRect);
            //int width = windowRect.right - windowRect.left;
            //int height = windowRect.bottom - windowRect.top;
            int    width   = 3840;
            int    height  = 2160; //hardcode for now, dimension of my monitor
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
            IntPtr hOld    = GDI32.SelectObject(hdcDest, hBitmap);

            GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
            GDI32.SelectObject(hdcDest, hOld);
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);
            Image img = Image.FromHbitmap(hBitmap);

            GDI32.DeleteObject(hBitmap);
            return(img);
        }
        public static Bitmap CaptureScreen()
        {
            IntPtr handle = User32.GetDesktopWindow();
            IntPtr hdcSrc = User32.GetWindowDC(handle);

            User32.RECT windowRect = new User32.RECT();
            User32.GetWindowRect(handle, ref windowRect);
            int    width   = (windowRect.right - windowRect.left);
            int    height  = (windowRect.bottom - windowRect.top);
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
            IntPtr hOld    = GDI32.SelectObject(hdcDest, hBitmap);

            GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
            GDI32.SelectObject(hdcDest, hOld);
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);
            Bitmap img = Image.FromHbitmap(hBitmap);

            GDI32.DeleteObject(hBitmap);
            GC.Collect();
            return(img);
        }
Example #5
0
        public Image CapWinBitBlt(IntPtr handle)
        {
            //int SRCCOPY = 0xcc0020;
            int SRCCOPY = 0x00EE0086;
            // 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, 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);
        }
Example #6
0
        /// <summary>
        /// Creates an Image object containing a screen shot of a specific window
        /// </summary>
        /// <param name="handle">The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
        /// <returns></returns>
        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);
            ScreenCapture.Width  = windowRect.right - windowRect.left;
            ScreenCapture.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);

            GC.Collect();
            GC.WaitForPendingFinalizers();

            return(img);
        }
Example #7
0
        public Image CaptureWindow(IntPtr handle, Rectangle area)
        {
            // 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 = (int)((windowRect.right - windowRect.left) * scalingFactor);
            //            int height = (int)((windowRect.bottom - windowRect.top) * scalingFactor);
            int x      = (int)(area.Left * ScalingFactor);
            int y      = (int)(area.Top * ScalingFactor);
            int width  = (int)(area.Width * ScalingFactor);
            int height = (int)(area.Height * ScalingFactor);
            // 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, x, y, 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);
        }
        public Image GetBitmapFromGameWindow()
        {
            var gameWindow = _windowHandler.GetGameWindow();

            if (gameWindow == IntPtr.Zero)
            {
                return(null);
            }

            var gameWindowDc = _windowHandler.GetGameWindowDC();

            if (gameWindowDc == IntPtr.Zero)
            {
                _windowHandler.ResetWindow();
                return(null);
            }

            var windowRect = _windowHandler.GetWindowRect();
            int width      = windowRect.Right - windowRect.Left;
            int height     = windowRect.Bottom - windowRect.Top;

            IntPtr hdcDest = GDI32.CreateCompatibleDC(gameWindowDc);
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(gameWindowDc, width, height);
            IntPtr hOld    = GDI32.SelectObject(hdcDest, hBitmap);

            GDI32.BitBlt(hdcDest, 0, 0, width, height, gameWindowDc, 0, 0, GDI32.SRCCOPY);
            GDI32.SelectObject(hdcDest, hOld);
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(gameWindow, gameWindowDc);

            Image image = Image.FromHbitmap(hBitmap);

            GDI32.DeleteObject(hBitmap);

            return(image);
        }
Example #9
0
        /// <summary>
        /// プライマリスクリーンの画像を取得する
        /// </summary>
        /// <returns>プライマリスクリーンの画像</returns>
        public static Bitmap CaptureRect(Rectangle rc)
        {
            //プライマリモニタのデバイスコンテキストを取得
            IntPtr hsrcDC = User32.GetDC(IntPtr.Zero);

            //Bitmapの作成
            Bitmap bmp = new Bitmap(rc.Width, rc.Height);

            //Graphicsの作成
            Graphics g = Graphics.FromImage(bmp);

            //Graphicsのデバイスコンテキストを取得
            IntPtr hdestDC = g.GetHdc();

            //Bitmapに画像をコピーする
            GDI32.BitBlt(hdestDC, 0, 0, bmp.Width, bmp.Height, hsrcDC, rc.Left, rc.Top, GDI32.SRCCOPY | GDI32.CAPTUREBLT);

            //解放
            g.ReleaseHdc(hdestDC);
            g.Dispose();
            User32.ReleaseDC(IntPtr.Zero, hsrcDC);

            return(bmp);
        }
        /// <summary>
        /// This method will use User32 code to capture the specified captureBounds from the screen
        /// </summary>
        /// <param name="captureBounds">Rectangle with the bounds to capture</param>
        /// <returns>Bitmap which is captured from the screen at the location specified by the captureBounds</returns>
        public static Bitmap CaptureRectangle(Rectangle captureBounds)
        {
            Bitmap returnBitmap = null;

            if (captureBounds.Height <= 0 || captureBounds.Width <= 0)
            {
                LOG.Warn("Nothing to capture, ignoring!");
                return(null);
            }
            LOG.Debug("CaptureRectangle Called!");

            // .NET GDI+ Solution, according to some post this has a GDI+ leak...
            // See http://connect.microsoft.com/VisualStudio/feedback/details/344752/gdi-object-leak-when-calling-graphics-copyfromscreen
            // Bitmap capturedBitmap = new Bitmap(captureBounds.Width, captureBounds.Height);
            // using (Graphics graphics = Graphics.FromImage(capturedBitmap)) {
            //	graphics.CopyFromScreen(captureBounds.Location, Point.Empty, captureBounds.Size, CopyPixelOperation.CaptureBlt);
            // }
            // capture.Image = capturedBitmap;
            // capture.Location = captureBounds.Location;

            using (SafeWindowDCHandle desktopDCHandle = SafeWindowDCHandle.fromDesktop()) {
                if (desktopDCHandle.IsInvalid)
                {
                    // Get Exception before the error is lost
                    Exception exceptionToThrow = CreateCaptureException("desktopDCHandle", captureBounds);
                    // throw exception
                    throw exceptionToThrow;
                }

                // create a device context we can copy to
                using (SafeCompatibleDCHandle safeCompatibleDCHandle = GDI32.CreateCompatibleDC(desktopDCHandle)) {
                    // Check if the device context is there, if not throw an error with as much info as possible!
                    if (safeCompatibleDCHandle.IsInvalid)
                    {
                        // Get Exception before the error is lost
                        Exception exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds);
                        // throw exception
                        throw exceptionToThrow;
                    }
                    // Create BITMAPINFOHEADER for CreateDIBSection
                    BITMAPINFOHEADER bmi = new BITMAPINFOHEADER(captureBounds.Width, captureBounds.Height, 24);

                    // Make sure the last error is set to 0
                    Win32.SetLastError(0);

                    // create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
                    IntPtr bits0;                     // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
                    using (SafeDibSectionHandle safeDibSectionHandle = GDI32.CreateDIBSection(desktopDCHandle, ref bmi, BITMAPINFOHEADER.DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0)) {
                        if (safeDibSectionHandle.IsInvalid)
                        {
                            // Get Exception before the error is lost
                            Exception exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds);
                            exceptionToThrow.Data.Add("hdcDest", safeCompatibleDCHandle.DangerousGetHandle().ToInt32());
                            exceptionToThrow.Data.Add("hdcSrc", desktopDCHandle.DangerousGetHandle().ToInt32());

                            // Throw so people can report the problem
                            throw exceptionToThrow;
                        }
                        // select the bitmap object and store the old handle
                        using (safeCompatibleDCHandle.SelectObject(safeDibSectionHandle)) {
                            // bitblt over (make copy)
                            GDI32.BitBlt(safeCompatibleDCHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDCHandle, captureBounds.X, captureBounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
                        }

                        // get a .NET image object for it
                        // A suggestion for the "A generic error occurred in GDI+." E_FAIL/0×80004005 error is to re-try...
                        bool success = false;
                        ExternalException exception = null;
                        for (int i = 0; i < 3; i++)
                        {
                            try {
                                // Collect all screens inside this capture
                                List <Screen> screensInsideCapture = new List <Screen>();
                                foreach (Screen screen in Screen.AllScreens)
                                {
                                    if (screen.Bounds.IntersectsWith(captureBounds))
                                    {
                                        screensInsideCapture.Add(screen);
                                    }
                                }
                                // Check all all screens are of an equal size
                                bool offscreenContent;
                                using (Region captureRegion = new Region(captureBounds)) {
                                    // Exclude every visible part
                                    foreach (Screen screen in screensInsideCapture)
                                    {
                                        captureRegion.Exclude(screen.Bounds);
                                    }
                                    // If the region is not empty, we have "offscreenContent"
                                    using (Graphics screenGraphics = Graphics.FromHwnd(User32.GetDesktopWindow())) {
                                        offscreenContent = !captureRegion.IsEmpty(screenGraphics);
                                    }
                                }
                                // Check if we need to have a transparent background, needed for offscreen content
                                if (offscreenContent)
                                {
                                    using (Bitmap tmpBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle())) {
                                        // Create a new bitmap which has a transparent background
                                        returnBitmap = ImageHelper.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution);
                                        // Content will be copied here
                                        using (Graphics graphics = Graphics.FromImage(returnBitmap)) {
                                            // For all screens copy the content to the new bitmap
                                            foreach (Screen screen in Screen.AllScreens)
                                            {
                                                Rectangle screenBounds = screen.Bounds;
                                                // Make sure the bounds are offsetted to the capture bounds
                                                screenBounds.Offset(-captureBounds.X, -captureBounds.Y);
                                                graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel);
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    // All screens, which are inside the capture, are of equal size
                                    // assign image to Capture, the image will be disposed there..
                                    returnBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle());
                                }
                                // We got through the capture without exception
                                success = true;
                                break;
                            } catch (ExternalException ee) {
                                LOG.Warn("Problem getting bitmap at try " + i + " : ", ee);
                                exception = ee;
                            }
                        }
                        if (!success)
                        {
                            LOG.Error("Still couldn't create Bitmap!");
                            if (exception != null)
                            {
                                throw exception;
                            }
                        }
                    }
                }
            }
            return(returnBitmap);
        }
Example #11
0
        /// <summary>
        /// This method will use User32 code to capture the specified captureBounds from the screen
        /// </summary>
        /// <param name="captureBounds">Rectangle with the bounds to capture</param>
        /// <returns>Bitmap which is captured from the screen at the location specified by the captureBounds</returns>
        public static Bitmap CaptureRectangle(Rectangle captureBounds)
        {
            Bitmap returnBitmap = null;

            if (captureBounds.Height <= 0 || captureBounds.Width <= 0)
            {
                LOG.Warn("Nothing to capture, ignoring!");
                return(null);
            }
            else
            {
                LOG.Debug("CaptureRectangle Called!");
            }

            // .NET GDI+ Solution, according to some post this has a GDI+ leak...
            // See http://connect.microsoft.com/VisualStudio/feedback/details/344752/gdi-object-leak-when-calling-graphics-copyfromscreen
            // Bitmap capturedBitmap = new Bitmap(captureBounds.Width, captureBounds.Height);
            // using (Graphics graphics = Graphics.FromImage(capturedBitmap)) {
            //	graphics.CopyFromScreen(captureBounds.Location, Point.Empty, captureBounds.Size, CopyPixelOperation.CaptureBlt);
            // }
            // capture.Image = capturedBitmap;
            // capture.Location = captureBounds.Location;

            // "P/Invoke" Solution for capturing the screen
            IntPtr hWndDesktop = User32.GetDesktopWindow();
            // get te hDC of the target window
            IntPtr hDCDesktop = User32.GetWindowDC(hWndDesktop);

            // Make sure the last error is set to 0
            Win32.SetLastError(0);

            // create a device context we can copy to
            IntPtr hDCDest = GDI32.CreateCompatibleDC(hDCDesktop);

            // Check if the device context is there, if not throw an error with as much info as possible!
            if (hDCDest == IntPtr.Zero)
            {
                // Get Exception before the error is lost
                Exception exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds);
                // Cleanup
                User32.ReleaseDC(hWndDesktop, hDCDesktop);
                // throw exception
                throw exceptionToThrow;
            }

            // Create BitmapInfoHeader for CreateDIBSection
            BitmapInfoHeader bmi = new BitmapInfoHeader(captureBounds.Width, captureBounds.Height, 24);

            // Make sure the last error is set to 0
            Win32.SetLastError(0);

            // create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
            IntPtr bits0;             // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
            IntPtr hDIBSection = GDI32.CreateDIBSection(hDCDesktop, ref bmi, BitmapInfoHeader.DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0);

            if (hDIBSection == IntPtr.Zero)
            {
                // Get Exception before the error is lost
                Exception exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds);
                exceptionToThrow.Data.Add("hdcDest", hDCDest.ToInt32());
                exceptionToThrow.Data.Add("hdcSrc", hDCDesktop.ToInt32());

                // clean up
                GDI32.DeleteDC(hDCDest);
                User32.ReleaseDC(hWndDesktop, hDCDesktop);

                // Throw so people can report the problem
                throw exceptionToThrow;
            }
            else
            {
                // select the bitmap object and store the old handle
                IntPtr hOldObject = GDI32.SelectObject(hDCDest, hDIBSection);

                // bitblt over (make copy)
                GDI32.BitBlt(hDCDest, 0, 0, captureBounds.Width, captureBounds.Height, hDCDesktop, captureBounds.X, captureBounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);

                // restore selection (old handle)
                GDI32.SelectObject(hDCDest, hOldObject);
                // clean up
                GDI32.DeleteDC(hDCDest);
                User32.ReleaseDC(hWndDesktop, hDCDesktop);

                // get a .NET image object for it
                // A suggestion for the "A generic error occurred in GDI+." E_FAIL/0×80004005 error is to re-try...
                bool success = false;
                ExternalException exception = null;
                for (int i = 0; i < 3; i++)
                {
                    try {
                        // assign image to Capture, the image will be disposed there..
                        returnBitmap = Bitmap.FromHbitmap(hDIBSection);
                        success      = true;
                        break;
                    } catch (ExternalException ee) {
                        LOG.Warn("Problem getting bitmap at try " + i + " : ", ee);
                        exception = ee;
                    }
                }
                if (!success)
                {
                    LOG.Error("Still couldn't create Bitmap!");
                    throw exception;
                }
                // free up the Bitmap object
                GDI32.DeleteObject(hDIBSection);
            }
            return(returnBitmap);
        }
Example #12
0
        public void CaptureScreen()
        {
            desktopName = User32.GetCurrentDesktop();
            lastFrame   = (Bitmap)currentFrame.Clone();
            graphic     = Graphics.FromImage(currentFrame);
            hDC         = User32.GetWindowDC(hWnd);
            graphDC     = graphic.GetHdc();
            try
            {
                var copyResult = GDI32.BitBlt(graphDC, 0, 0, totalWidth, totalHeight, hDC, 0 + offsetX, 0 + offsetY, GDI32.TernaryRasterOperations.SRCCOPY);
                if (!copyResult)
                {
                    graphic.ReleaseHdc(graphDC);
                    graphic.Clear(System.Drawing.Color.White);
                    var font = new Font(System.Drawing.FontFamily.GenericSansSerif, 36, System.Drawing.FontStyle.Bold);
                    graphic.DrawString("Waiting for screen capture...", font, System.Drawing.Brushes.Black, new PointF((totalWidth / 2), (float)(totalHeight * .35)), new StringFormat()
                    {
                        Alignment = StringAlignment.Center
                    });
                    graphic.DrawString("(If this screen does not refresh, you may need to reconnect.)", new Font("GenericSansSerif", 24), System.Drawing.Brushes.Black, new PointF((totalWidth / 2), (float)(totalHeight * .55)), new StringFormat()
                    {
                        Alignment = StringAlignment.Center
                    });

                    if (!AditClient.DesktopSwitchPending)
                    {
                        SwitchDesktops();
                    }
                }
                else
                {
                    graphic.ReleaseHdc(graphDC);
                    User32.ReleaseDC(hWnd, hDC);
                }

#if DEBUG
                FPSStack.RemoveAll(x => DateTime.Now - x > TimeSpan.FromSeconds(1));
                FPSStack.Add(DateTime.Now);
                var path = new GraphicsPath();
                path.AddString("FPS: " + FPSStack.Count.ToString(), System.Drawing.FontFamily.GenericSansSerif, (int)System.Drawing.FontStyle.Bold, 48, new PointF(25, 25), StringFormat.GenericDefault);
                graphic.DrawPath(new System.Drawing.Pen(System.Drawing.Brushes.Black, 48 / 4), path);
                graphic.FillPath(System.Drawing.Brushes.White, path);
#endif
            }
            catch (Exception ex)
            {
                Utilities.WriteToLog(ex);
                if (graphDC != IntPtr.Zero)
                {
                    graphic.ReleaseHdc(graphDC);
                }
                if (hDC != IntPtr.Zero)
                {
                    User32.ReleaseDC(hWnd, hDC);
                }
                if (!AditClient.DesktopSwitchPending)
                {
                    SwitchDesktops();
                }
            }
        }
        /// <summary>
        /// Creates an Image object containing a screen shot of a specific window
        /// </summary>
        /// <param name="handle">The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
        /// <param name="height">The height.</param>
        /// <param name="width">The width.</param>
        /// <param name="nXDest">The x-coordinate, in logical units, of the upper-left corner of the destination rectangle.</param>
        /// <param name="nYDest">The y-coordinate, in logical units, of the upper-left corner of the destination rectangle.</param>
        /// <param name="nXSrc">The x-coordinate, in logical units, of the upper-left corner of the source rectangle.</param>
        /// <param name="nYSrc">The y-coordinate, in logical units, of the upper-left corner of the source rectangle.</param>
        /// <returns></returns>
        /// <remarks>There is aproblem with OpenGL and other high end rendering libraries. They can prvent from generating screenshots. Turn them off. </remarks>
        public static Image CaptureWindow(IntPtr handle, int height, int width, int nXSrc = 0, int nYSrc = 0, int nXDest = 0, int nYDest = 0)
        {
            IntPtr hBitmap = IntPtr.Zero;
            IntPtr hOld    = IntPtr.Zero;
            // get a .NET image object for it
            Image img = null;

            if (!ScreenCapture.User32.IsWindow(handle))
            {
                if (Debug)
                {
                    Logger.Instance.Log(LogPriority.DEBUG, "Screencapture", "[ERROR] Fatal error in Screen capturer: Given handle to capture (" + handle + ") is not a window!");
                }
                //TODO: how to handle this
                return(img);
            }

            // get the device context (DC) for the entire target window
            // IntPtr hdcSrc = User32.GetWindowDC(handle);
            // IntPtr hdcSrc = User32.GetDC(handle); // do not use this because then the mapping of wnd content position to img position does not longer fit.
            IntPtr hdcSrc = getDeviceContext(handle);
            // create a device context we can copy to
            // IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            // IntPtr hdcDest = GDI32.CreateCompatibleDC(IntPtr.Zero); // If this handle is NULL, the function creates a memory DC compatible with the application's current screen.
            IntPtr hdcDest = getCompatibleDeviceContext(hdcSrc);

            if (hdcDest == IntPtr.Zero)
            {
                if (Debug)
                {
                    System.Console.WriteLine(Marshal.GetLastWin32Error());
                }

                if (Debug)
                {
                    Logger.Instance.Log(LogPriority.DEBUG, "Screencapture", "[ERROR] Fatal error in Screen capturer: Can't get compatible DC!");
                }
                //TODO: how to handle this
                return(img);
            }

            try
            {
                // create a bitmap we can copy it to,
                // using GetDeviceCaps to get the width/height
                hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
                // IntPtr hBitmap = GDI32.CreateCompatibleBitmap(scrDC, width, height);
                if (hBitmap == IntPtr.Zero)
                {
                    IntPtr hDest = GDI32.CreateCompatibleDC(IntPtr.Zero);
                    hBitmap = GDI32.CreateCompatibleBitmap(hDest, width, height);

                    if (hBitmap == IntPtr.Zero)
                    {
                        if (Debug)
                        {
                            System.Console.WriteLine(Marshal.GetLastWin32Error());
                        }
                        //FIXME: how to handle this? Stackoverflow exception ?
                        if (Debug)
                        {
                            Logger.Instance.Log(LogPriority.DEBUG, "Screencapture", "[ERROR] Fatal error in Screen capturer: Can't create an image from the given DC: " + hdcSrc + " !!!");
                        }
                        return(img);
                    }
                }

                // select the bitmap object
                hOld = GDI32.SelectObject(hdcDest, hBitmap);
                // copy the bit blocks of the window bitmap to the save bitmap
                bool success = GDI32.BitBlt(hdcDest, nXDest, nYDest, width, height, hdcSrc, nXSrc, nYSrc,
                                            (int)(System.Drawing.CopyPixelOperation.SourceCopy | System.Drawing.CopyPixelOperation.CaptureBlt)
                                            // GDI32.SRCCOPY
                                            );
                if (!success)
                {
                    if (Debug)
                    {
                        System.Console.WriteLine(Marshal.GetLastWin32Error());
                    }
                    //TODO: how to handle this
                    if (Debug)
                    {
                        Logger.Instance.Log(LogPriority.DEBUG, "Screencapture", "[ERROR] Fatal error in Screen capturer: Can't copy data to hbitmap!!!");
                    }

                    // force getting new device context. Helps sometimes to unlock the hanging mechanism.
                    hdcDest = getCompatibleDeviceContext(IntPtr.Zero);
                    hdcSrc  = getDeviceContext(User32.GetDesktopWindow());

                    success = GDI32.BitBlt(hdcDest, nXDest, nYDest, width, height, hdcSrc, nXSrc, nYSrc,
                                           (int)(System.Drawing.CopyPixelOperation.SourceCopy /*System.Drawing.CopyPixelOperation.CaptureBlt*/)
                                           // GDI32.SRCCOPY
                                           );
                    if (!success)
                    {
                        return(img);
                    }
                }
                // restore selection
                GDI32.SelectObject(hdcDest, hOld);


                // clean up
                // User32.ReleaseDC(handle, hdcSrc);
                // GDI32.DeleteDC(hdcDest);

                if (hBitmap != null && hBitmap != IntPtr.Zero)
                {
                    img = Image.FromHbitmap(hBitmap);
                }
                else
                {
                }

                return(img);
            }
            catch { return(img); }
            finally
            {
                //_capCount++;
                // free up the Bitmap object
                GDI32.DeleteObject(hBitmap);
                // GDI32.DeleteObject(hdcDest);
                GDI32.DeleteObject(hOld);
                // GDI32.DeleteObject(hdcSrc);
            }
        }
Example #14
0
        private void capturarPantallaCompletaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Opacity       = 0;
            this.ShowInTaskbar = false;
            IntPtr handle = User32.GetDesktopWindow();
            // 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);

            /*
             *
             * CURSORINFO pci;
             * pci.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(CURSORINFO));
             * using (Graphics g = Graphics.FromImage(img))
             * {
             *  if (GetCursorInfo(out pci))
             *  {
             *      if (pci.flags == CURSOR_SHOWING)
             *      {
             *          DrawIcon(g.GetHdc(), pci.ptScreenPos.x, pci.ptScreenPos.y, pci.hCursor);
             *          g.ReleaseHdc();
             *      }
             *  }
             * }*/

            string pathTemp = Path.GetTempPath() + "Desktop_" + RandomString(4) + ".png";


            img.Save(pathTemp, ImageFormat.Png);

            files.Add(pathTemp);

            listView1.Items.Add(new ListViewItem(new string[] { new FileInfo(pathTemp).Name, "Esperando" }));
            this.Opacity       = 1;
            this.ShowInTaskbar = true;
        }
Example #15
0
 internal static bool BitBlockTransfer(IntPtr targetDC, int targetX, int targetY, int width, int height, IntPtr sourceDC, int sourceX, int sourceY)
 {
     return(GDI32.BitBlt(targetDC, targetX, targetY, width, height, sourceDC, sourceX, sourceY, SRCCOPY));
 }
Example #16
0
        /// <summary>
        /// FreeImage method
        /// </summary>
        /// <param name="bmp"></param>

        /*
         * public static void FI_ConvertSave(Bitmap bmp)
         * {
         *  if (bmp != null)
         *  {
         *      using (FreeImageAPI.FreeImageBitmap fiBitmap = FreeImageAPI.FreeImageBitmap.FromHbitmap(bmp.GetHbitmap()))
         *      {
         *          if (fiBitmap.ColorDepth > 24)
         *          {
         *              fiBitmap.ConvertColorDepth(FreeImageAPI.FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP);
         *          }
         *          for (int i = 16; i < 256; i++)
         *              fiBitmap.Palette.Data[i] = new FreeImageAPI.RGBQUAD(Color.White);
         *
         *          FreeImageAPI.Palette pl = new FreeImageAPI.Palette(256);
         *          pl.CreateGrayscalePalette();
         *          //quantize using the NeuQuant neural-net quantization algorithm
         *          fiBitmap.Quantize(FreeImageAPI.FREE_IMAGE_QUANTIZE.FIQ_NNQUANT, 16, pl);
         *
         *
         *
         *          fiBitmap.Save("test_FreeImageOutput.png", FreeImageAPI.FREE_IMAGE_FORMAT.FIF_PNG, FreeImageAPI.FREE_IMAGE_SAVE_FLAGS.PNG_Z_BEST_COMPRESSION);
         *          //bmp = fiBitmap.ToBitmap();
         *          //ms = new MemoryStream();
         *          //fiBitmap.Save(ms, FreeImageAPI.FREE_IMAGE_FORMAT.FIF_PNG, FreeImageAPI.FREE_IMAGE_SAVE_FLAGS.PNG_Z_DEFAULT_COMPRESSION);
         *      }
         *      bmp.Dispose();
         *  }
         * }
         */

        // From wischik.com
        static Bitmap CopyToBpp(System.Drawing.Bitmap b, int bpp)
        {
            if (bpp != 1 && bpp != 8)
            {
                throw new System.ArgumentException("1 or 8", "bpp");
            }

            // Plan: built into Windows GDI is the ability to convert
            // bitmaps from one format to another. Most of the time, this
            // job is actually done by the graphics hardware accelerator card
            // and so is extremely fast. The rest of the time, the job is done by
            // very fast native code.
            // We will call into this GDI functionality from C#. Our plan:
            // (1) Convert our Bitmap into a GDI hbitmap (ie. copy unmanaged->managed)
            // (2) Create a GDI monochrome hbitmap
            // (3) Use GDI "BitBlt" function to copy from hbitmap into monochrome (as above)
            // (4) Convert the monochrone hbitmap into a Bitmap (ie. copy unmanaged->managed)

            int    w   = b.Width;
            int    h   = b.Height;
            IntPtr hbm = b.GetHbitmap(); // this is step (1)

            //
            // Step (2): create the monochrome bitmap.
            // "BITMAPINFO" is an interop-struct which we define below.
            // In GDI terms, it's a BITMAPHEADERINFO followed by an array of two RGBQUADs
            GDI32.BITMAPINFOHEADER bmi = new GDI32.BITMAPINFOHEADER();
            bmi.biSize          = 40; // the size of the BITMAPHEADERINFO struct
            bmi.biWidth         = w;
            bmi.biHeight        = h;
            bmi.biPlanes        = 1;                     // "planes" are confusing. We always use just 1. Read MSDN for more info.
            bmi.biBitCount      = (ushort)bpp;           // ie. 1bpp or 8bpp
            bmi.biCompression   = (uint)GdiFlags.BI_RGB; // ie. the pixels in our RGBQUAD table are stored as RGBs, not palette indexes
            bmi.biSizeImage     = (uint)(((w + 7) & 0xFFFFFFF8) * h / 8);
            bmi.biXPelsPerMeter = 1000000;               // not really important
            bmi.biYPelsPerMeter = 1000000;               // not really important
            // Now for the colour table.
            uint ncols = (uint)1 << bpp;                 // 2 colours for 1bpp; 256 colours for 8bpp

            bmi.biClrUsed      = ncols;
            bmi.biClrImportant = ncols;
            bmi.cols           = new uint[256]; // The structure always has fixed size 256, even if we end up using fewer colours
            if (bpp == 1)
            {
                bmi.cols[0] = GDI32.MAKERGB(0, 0, 0); bmi.cols[1] = GDI32.MAKERGB(255, 255, 255);
            }
            else
            {
                for (int i = 0; i < ncols; i++)
                {
                    bmi.cols[i] = GDI32.MAKERGB(i, i, i);
                }
            }
            // For 8bpp we've created an palette with just greyscale colours.
            // You can set up any palette you want here. Here are some possibilities:
            // greyscale: for (int i=0; i<256; i++) bmi.cols[i]=MAKERGB(i,i,i);
            bmi.biClrUsed = 216; bmi.biClrImportant = 216; int[] colv = new int[6] {
                0, 51, 102, 153, 204, 255
            };
            for (int i = 0; i < 216; i++)
            {
                bmi.cols[i] = GDI32.MAKERGB(colv[i / 36], colv[(i / 6) % 6], colv[i % 6]);
            }
            // rainbow: bmi.biClrUsed=216; bmi.biClrImportant=216; int[] colv=new int[6]{0,51,102,153,204,255};
            //          for (int i=0; i<216; i++) bmi.cols[i]=GDI32.MAKERGB(colv[i/36],colv[(i/6)%6],colv[i%6]);
            // optimal: a difficult topic: http://en.wikipedia.org/wiki/Color_quantization
            //
            // Now create the indexed bitmap "hbm0"
            IntPtr bits0; // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
            IntPtr hbm0 = GDI32.CreateDIBSection(IntPtr.Zero, ref bmi, (uint)GdiFlags.DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0);
            //
            // Step (3): use GDI's BitBlt function to copy from original hbitmap into monocrhome bitmap
            // GDI programming is kind of confusing... nb. The GDI equivalent of "Graphics" is called a "DC".
            IntPtr sdc = USER32.GetDC(IntPtr.Zero);       // First we obtain the DC for the screen
            // Next, create a DC for the original hbitmap
            IntPtr hdc = GDI32.CreateCompatibleDC(sdc);

            GDI32.SelectObject(hdc, hbm);
            // and create a DC for the monochrome hbitmap
            IntPtr hdc0 = GDI32.CreateCompatibleDC(sdc);

            GDI32.SelectObject(hdc0, hbm0);
            // Now we can do the BitBlt:
            GDI32.BitBlt(hdc0, 0, 0, w, h, hdc, 0, 0, TernaryRasterOperations.SRCCOPY);
            // Step (4): convert this monochrome hbitmap back into a Bitmap:
            System.Drawing.Bitmap b0 = System.Drawing.Bitmap.FromHbitmap(hbm0);
            //
            // Finally some cleanup.
            GDI32.DeleteDC(hdc);
            GDI32.DeleteDC(hdc0);
            USER32.ReleaseDC(IntPtr.Zero, sdc);
            GDI32.DeleteObject(hbm);
            GDI32.DeleteObject(hbm0);
            //
            return(b0);
        }
Example #17
0
        private void CaptureFrame()
        {
            int MSBETWEENCAPTURES = 1000 / framesPerSecond;
            int msToNextCapture   = MSBETWEENCAPTURES;

            stopwatch.Reset();
            while (!stop)
            {
                stopwatch.Start();
                Point captureLocation;
                if (recordingWindow != null)
                {
                    recordingWindow.Reset();
                    captureLocation = recordingWindow.Location;
                }
                else
                {
                    captureLocation = new Point(recordingRectangle.X, recordingRectangle.Y);
                }
                // "Capture"
                GDI32.BitBlt(hDCDest, 0, 0, recordingSize.Width, recordingSize.Height, hDCDesktop, captureLocation.X, captureLocation.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);

                // Mouse
                if (RecordMouse)
                {
                    CursorInfo cursorInfo = new CursorInfo();
                    cursorInfo.cbSize = Marshal.SizeOf(cursorInfo);
                    Point mouseLocation = Cursor.Position;
                    mouseLocation.Offset(-captureLocation.X, -captureLocation.Y);
                    if (User32.GetCursorInfo(out cursorInfo))
                    {
                        User32.DrawIcon(hDCDest, mouseLocation.X, mouseLocation.Y, cursorInfo.hCursor);
                    }
                }
                // add to avi
                try {
                    aviWriter.AddLowLevelFrame(bits0);
                } catch (Exception) {
                    LOG.Error("Error adding frame to avi, stopping capturing.");
                    break;
                }

                int restTime = (int)(msToNextCapture - stopwatch.ElapsedMilliseconds);

                // Set time to next capture, we correct it if needed later.
                msToNextCapture = MSBETWEENCAPTURES;
                if (restTime > 0)
                {
                    // We were fast enough, we wait for next capture
                    Thread.Sleep(restTime);
                }
                else if (restTime < 0)
                {
                    // Compensating, as we took to long
                    int framesToSkip   = ((-restTime) / MSBETWEENCAPTURES);
                    int leftoverMillis = (-restTime) % MSBETWEENCAPTURES;
                    //LOG.InfoFormat("Adding {0} empty frames to avi, leftover millis is {1}, sleeping {2} (of {3} total)", framesToSkip, leftover, sleepMillis, MSBETWEENCAPTURES);
                    aviWriter.AddEmptyFrames(framesToSkip);

                    // check how bad it is, if we only missed our target by a few millis we hope the next capture corrects this
                    if (leftoverMillis > 0 && leftoverMillis <= 2)
                    {
                        // subtract the leftover from the millis to next capture, do nothing else
                        msToNextCapture -= leftoverMillis;
                    }
                    else if (leftoverMillis > 0)
                    {
                        // it's more, we add an empty frame
                        aviWriter.AddEmptyFrames(1);
                        // we sleep to the next time and
                        int sleepMillis = MSBETWEENCAPTURES - leftoverMillis;
                        // Sleep to next capture
                        Thread.Sleep(sleepMillis);
                    }
                }
                stopwatch.Reset();
            }
            Cleanup();
        }
Example #18
0
        private async Task SendFrame()
        {
            IntPtr hWnd    = IntPtr.Zero;
            IntPtr hDC     = IntPtr.Zero;
            IntPtr graphDC = IntPtr.Zero;

            try
            {
                hWnd    = User32.GetDesktopWindow();
                hDC     = User32.GetWindowDC(hWnd);
                graphDC = Graphic.GetHdc();
                var copyResult = GDI32.BitBlt(graphDC, 0, 0, screenShot.TotalWidth, screenShot.TotalHeight, hDC, 0 + offsetX, 0 + offsetY, GDI32.TernaryRasterOperations.SRCCOPY | GDI32.TernaryRasterOperations.CAPTUREBLT);
                if (!copyResult)
                {
                    Graphic.ReleaseHdc(graphDC);
                    Graphic.Clear(System.Drawing.Color.White);
                    var font = new Font(System.Drawing.FontFamily.GenericSansSerif, 30, System.Drawing.FontStyle.Bold);
                    Graphic.DrawString("Waiting for screen capture...", font, System.Drawing.Brushes.Black, new PointF((screenShot.TotalWidth / 2), screenShot.TotalHeight / 2), new StringFormat()
                    {
                        Alignment = StringAlignment.Center
                    });
                }
                else
                {
                    Graphic.ReleaseHdc(graphDC);
                    User32.ReleaseDC(hWnd, hDC);
                }

                // Get cursor information to draw on the screenshot.
                var ci = new User32.CursorInfo();
                ci.cbSize = Marshal.SizeOf(ci);
                User32.GetCursorInfo(out ci);
                if (ci.flags == User32.CURSOR_SHOWING)
                {
                    using (var icon = System.Drawing.Icon.FromHandle(ci.hCursor))
                    {
                        Graphic.DrawIcon(icon, ci.ptScreenPos.x, ci.ptScreenPos.y);
                    }
                }
                if (sendFullScreenshot)
                {
                    var request = new
                    {
                        Type   = "Bounds",
                        Width  = screenShot.TotalWidth,
                        Height = screenShot.TotalHeight
                    };
                    await SocketSend(request);

                    using (var ms = new MemoryStream())
                    {
                        screenShot.CurrentFrame.Save(ms, ImageFormat.Jpeg);
                        ms.WriteByte(0);
                        ms.WriteByte(0);
                        ms.WriteByte(0);
                        ms.WriteByte(0);
                        ms.WriteByte(0);
                        ms.WriteByte(0);
                        await Socket.SendAsync(new ArraySegment <byte>(ms.ToArray()), WebSocketMessageType.Binary, true, CancellationToken.None);

                        sendFullScreenshot = false;
                        return;
                    }
                }
                NewData = screenShot.GetNewData();
                if (NewData == null)
                {
                    await Task.Delay(100);

                    // Ignore async warning here since it's intentional.  This is to prevent deadlock.
#pragma warning disable
                    SendFrame();
#pragma warning restore
                }
                else
                {
                    using (var ms = new MemoryStream())
                    {
                        screenShot.SaveCroppedFrame(ms);
                        // Add x,y coordinates of top-left of image so receiver knows where to draw it.
                        foreach (var metaByte in NewData)
                        {
                            ms.WriteByte(metaByte);
                        }
                        await Socket.SendAsync(new ArraySegment <byte>(ms.ToArray()), WebSocketMessageType.Binary, true, CancellationToken.None);
                    }
                }
                screenShot.CloneLastFrame();
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
                if (graphDC != IntPtr.Zero)
                {
                    Graphic.ReleaseHdc(graphDC);
                }
                if (hDC != IntPtr.Zero)
                {
                    User32.ReleaseDC(hWnd, hDC);
                }
                capturing                  = false;
                stackMain.Visibility       = Visibility.Collapsed;
                stackReconnect.Visibility  = Visibility.Visible;
                textAgentStatus.FontWeight = FontWeights.Normal;
                textAgentStatus.Foreground = new SolidColorBrush(Colors.Black);
                textAgentStatus.Text       = "Not Connected";
            }
        }
Example #19
0
        static Icon CaptureCursor()
        {
            USER32.CURSORINFO cursorInfo = new USER32.CURSORINFO();
            cursorInfo.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(cursorInfo);
            if (!USER32.GetCursorInfo(out cursorInfo))
            {
                return(null);
            }

            if (cursorInfo.flags != USER32.CURSORINFOFlags.CURSOR_SHOWING)
            {
                return(null);
            }

            IntPtr hicon = USER32.CopyIcon(cursorInfo.hCursor);

            if (hicon == IntPtr.Zero)
            {
                return(null);
            }

            USER32.ICONINFO iconInfo;
            if (!USER32.GetIconInfo(hicon, out iconInfo))
            {
                return(null);
            }

            //x = cursorInfo.ptScreenPos.X - ((int)iconInfo.xHotspot);
            //y = cursorInfo.ptScreenPos.Y - ((int)iconInfo.yHotspot);

            using (Bitmap maskBitmap = Bitmap.FromHbitmap(iconInfo.hbmMask))
            {
                // Is this a monochrome cursor?
                if (maskBitmap.Height == maskBitmap.Width * 2)
                {
                    Bitmap resultBitmap = new Bitmap(maskBitmap.Width, maskBitmap.Width);

                    Graphics desktopGraphics = Graphics.FromHwnd(USER32.GetDesktopWindow());
                    IntPtr   desktopHdc      = desktopGraphics.GetHdc();

                    IntPtr maskHdc = GDI32.CreateCompatibleDC(desktopHdc);
                    IntPtr oldPtr  = GDI32.SelectObject(maskHdc, maskBitmap.GetHbitmap());

                    using (Graphics resultGraphics = Graphics.FromImage(resultBitmap))
                    {
                        IntPtr resultHdc = resultGraphics.GetHdc();

                        // These two operation will result in a black cursor over a white background.
                        // Later in the code, a call to MakeTransparent() will get rid of the white background.
                        GDI32.BitBlt(resultHdc, 0, 0, 32, 32, maskHdc, 0, 32, TernaryRasterOperations.SRCCOPY);
                        GDI32.BitBlt(resultHdc, 0, 0, 32, 32, maskHdc, 0, 0, TernaryRasterOperations.SRCINVERT);

                        resultGraphics.ReleaseHdc(resultHdc);
                    }

                    IntPtr newPtr = GDI32.SelectObject(maskHdc, oldPtr);
                    USER32.DeleteObject(newPtr);
                    GDI32.DeleteDC(maskHdc);
                    desktopGraphics.ReleaseHdc(desktopHdc);

                    // Remove the white background from the BitBlt calls,
                    // resulting in a black cursor over a transparent background.
                    resultBitmap.MakeTransparent(Color.White);
                    return(Icon.FromHandle(resultBitmap.GetHicon()));
                }
            }

            return(Icon.FromHandle(hicon));
        }
        // https://www.codeproject.com/Articles/546006/Screen-Capture-on-Multiple-Monitors
        //function to capture screen section
        public static Image CaptureScreen(int x, int y, int width, int height)
        {
            //create DC for the entire virtual screen
            IntPtr hdcSrc  = GDI32.CreateDC("DISPLAY", null, null, IntPtr.Zero);
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);

            GDI32.SelectObject(hdcDest, hBitmap);

            // set the destination area White - a little complicated
            Bitmap   bmp = new Bitmap(width, height);
            Image    ii  = (Image)bmp;
            Graphics gf  = Graphics.FromImage(ii);
            IntPtr   hdc = gf.GetHdc();

            //use whiteness flag to make destination screen white
            GDI32.BitBlt(hdcDest, 0, 0, width, height, hdc, 0, 0, 0x00FF0062);
            gf.Dispose();
            ii.Dispose();
            bmp.Dispose();

            //Now copy the areas from each screen on the destination hbitmap
            Screen[] screendata = Screen.AllScreens;
            int      X, X1, Y, Y1;

            for (int i = 0; i < screendata.Length; i++)
            {
                if (screendata[i].Bounds.X > (x + width) || (screendata[i].Bounds.X +
                                                             screendata[i].Bounds.Width) < x || screendata[i].Bounds.Y > (y + height) ||
                    (screendata[i].Bounds.Y + screendata[i].Bounds.Height) < y)                  // no common area
                {
                }
                else
                {
                    // something  common
                    if (x < screendata[i].Bounds.X)
                    {
                        X = screendata[i].Bounds.X;
                    }
                    else
                    {
                        X = x;
                    }
                    if ((x + width) > (screendata[i].Bounds.X + screendata[i].Bounds.Width))
                    {
                        X1 = screendata[i].Bounds.X + screendata[i].Bounds.Width;
                    }
                    else
                    {
                        X1 = x + width;
                    }
                    if (y < screendata[i].Bounds.Y)
                    {
                        Y = screendata[i].Bounds.Y;
                    }
                    else
                    {
                        Y = y;
                    }
                    if ((y + height) > (screendata[i].Bounds.Y + screendata[i].Bounds.Height))
                    {
                        Y1 = screendata[i].Bounds.Y + screendata[i].Bounds.Height;
                    }
                    else
                    {
                        Y1 = y + height;
                    }
                    // Main API that does memory data transfer
                    // SRCCOPY AND CAPTUREBLT
                    GDI32.BitBlt(hdcDest, X - x, Y - y, X1 - X, Y1 - Y, hdcSrc, X, Y, 0x40000000 | 0x00CC0020);
                }
            }

            // send image to clipboard
            Image imf = Image.FromHbitmap(new IntPtr((int)hBitmap));

            //Clipboard.SetImage(imf);
            GDI32.DeleteDC(hdcSrc);
            GDI32.DeleteDC(hdcDest);
            GDI32.DeleteObject(hBitmap);
            return(imf);
        }