/// <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); }
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); }
/// <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); }
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); }
/// <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); }
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); }
/// <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); }
/// <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); }
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); } }
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; }
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)); }
/// <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); }
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(); }
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"; } }
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); }