/// <summary> /// Capture the supplied Window /// </summary> /// <param name="windowToCapture">Window to capture</param> /// <param name="captureForWindow">The capture to store the details</param> /// <param name="windowCaptureMode">What WindowCaptureMode to use</param> /// <returns></returns> public static ICapture CaptureWindow(WindowDetails windowToCapture, ICapture captureForWindow, WindowCaptureMode windowCaptureMode) { if (captureForWindow == null) { captureForWindow = new Capture(); } Rectangle windowRectangle = windowToCapture.WindowRectangle; // When Vista & DWM (Aero) enabled bool dwmEnabled = DWM.isDWMEnabled(); // get process name to be able to exclude certain processes from certain capture modes using (Process process = windowToCapture.Process) { bool isAutoMode = windowCaptureMode == WindowCaptureMode.Auto; // For WindowCaptureMode.Auto we check: // 1) Is window IE, use IE Capture // 2) Is Windows >= Vista & DWM enabled: use DWM // 3) Otherwise use GDI (Screen might be also okay but might lose content) if (isAutoMode) { if (conf.IECapture && IECaptureHelper.IsIEWindow(windowToCapture)) { try { ICapture ieCapture = IECaptureHelper.CaptureIE(captureForWindow, windowToCapture); if (ieCapture != null) { return ieCapture; } } catch (Exception ex) { LOG.WarnFormat("Problem capturing IE, skipping to normal capture. Exception message was: {0}", ex.Message); } } // Take default screen windowCaptureMode = WindowCaptureMode.Screen; // Change to GDI, if allowed if (!windowToCapture.isMetroApp && WindowCapture.IsGdiAllowed(process)) { if (!dwmEnabled && isWPF(process)) { // do not use GDI, as DWM is not enabled and the application uses PresentationFramework.dll -> isWPF LOG.InfoFormat("Not using GDI for windows of process {0}, as the process uses WPF", process.ProcessName); } else { windowCaptureMode = WindowCaptureMode.GDI; } } // Change to DWM, if enabled and allowed if (dwmEnabled) { if (windowToCapture.isMetroApp || WindowCapture.IsDwmAllowed(process)) { windowCaptureMode = WindowCaptureMode.Aero; } } } else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) { if (!dwmEnabled || (!windowToCapture.isMetroApp && !WindowCapture.IsDwmAllowed(process))) { // Take default screen windowCaptureMode = WindowCaptureMode.Screen; // Change to GDI, if allowed if (WindowCapture.IsGdiAllowed(process)) { windowCaptureMode = WindowCaptureMode.GDI; } } } else if (windowCaptureMode == WindowCaptureMode.GDI && !WindowCapture.IsGdiAllowed(process)) { // GDI not allowed, take screen windowCaptureMode = WindowCaptureMode.Screen; } LOG.InfoFormat("Capturing window with mode {0}", windowCaptureMode); bool captureTaken = false; windowRectangle.Intersect(captureForWindow.ScreenBounds); // Try to capture while (!captureTaken) { ICapture tmpCapture = null; switch (windowCaptureMode) { case WindowCaptureMode.GDI: if (WindowCapture.IsGdiAllowed(process)) { if (windowToCapture.Iconic) { // Restore the window making sure it's visible! windowToCapture.Restore(); } else { windowToCapture.ToForeground(); } tmpCapture = windowToCapture.CaptureGDIWindow(captureForWindow); if (tmpCapture != null) { // check if GDI capture any good, by comparing it with the screen content int blackCountGDI = ImageHelper.CountColor(tmpCapture.Image, Color.Black, false); int GDIPixels = tmpCapture.Image.Width * tmpCapture.Image.Height; int blackPercentageGDI = (blackCountGDI * 100) / GDIPixels; if (blackPercentageGDI >= 1) { int screenPixels = windowRectangle.Width * windowRectangle.Height; using (ICapture screenCapture = new Capture()) { screenCapture.CaptureDetails = captureForWindow.CaptureDetails; if (WindowCapture.CaptureRectangleFromDesktopScreen(screenCapture, windowRectangle) != null) { int blackCountScreen = ImageHelper.CountColor(screenCapture.Image, Color.Black, false); int blackPercentageScreen = (blackCountScreen * 100) / screenPixels; if (screenPixels == GDIPixels) { // "easy compare", both have the same size // If GDI has more black, use the screen capture. if (blackPercentageGDI > blackPercentageScreen) { LOG.Debug("Using screen capture, as GDI had additional black."); // changeing the image will automatically dispose the previous tmpCapture.Image = screenCapture.Image; // Make sure it's not disposed, else the picture is gone! screenCapture.NullImage(); } } else if (screenPixels < GDIPixels) { // Screen capture is cropped, window is outside of screen if (blackPercentageGDI > 50 && blackPercentageGDI > blackPercentageScreen) { LOG.Debug("Using screen capture, as GDI had additional black."); // changeing the image will automatically dispose the previous tmpCapture.Image = screenCapture.Image; // Make sure it's not disposed, else the picture is gone! screenCapture.NullImage(); } } else { // Use the GDI capture by doing nothing LOG.Debug("This should not happen, how can there be more screen as GDI pixels?"); } } } } } } if (tmpCapture != null) { captureForWindow = tmpCapture; captureTaken = true; } else { // A problem, try Screen windowCaptureMode = WindowCaptureMode.Screen; } break; case WindowCaptureMode.Aero: case WindowCaptureMode.AeroTransparent: if (windowToCapture.isMetroApp || WindowCapture.IsDwmAllowed(process)) { tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode); } if (tmpCapture != null) { captureForWindow = tmpCapture; captureTaken = true; } else { // A problem, try GDI windowCaptureMode = WindowCaptureMode.GDI; } break; default: // Screen capture if (windowToCapture.Iconic) { // Restore the window making sure it's visible! windowToCapture.Restore(); } else { windowToCapture.ToForeground(); } try { captureForWindow = WindowCapture.CaptureRectangleFromDesktopScreen(captureForWindow, windowRectangle); captureTaken = true; } catch (Exception e) { LOG.Error("Problem capturing", e); return null; } break; } } } if (captureForWindow != null) { if (windowToCapture != null) { captureForWindow.CaptureDetails.Title = windowToCapture.Text; } } return captureForWindow; }
/// <summary> /// Capture the supplied Window /// </summary> /// <param name="windowToCapture">Window to capture</param> /// <param name="captureForWindow">The capture to store the details</param> /// <param name="windowCaptureMode">What WindowCaptureMode to use</param> /// <returns></returns> public static ICapture CaptureWindow(WindowDetails windowToCapture, ICapture captureForWindow, WindowCaptureMode windowCaptureMode) { if (captureForWindow == null) { captureForWindow = new Capture(); } Rectangle windowRectangle = windowToCapture.WindowRectangle; if (windowToCapture.Iconic) { // Restore the window making sure it's visible! windowToCapture.Restore(); } // When Vista & DWM (Aero) enabled bool dwmEnabled = DWM.isDWMEnabled(); // get process name to be able to exclude certain processes from certain capture modes Process process = windowToCapture.Process; bool isAutoMode = windowCaptureMode == WindowCaptureMode.Auto; // For WindowCaptureMode.Auto we check: // 1) Is window IE, use IE Capture // 2) Is Windows >= Vista & DWM enabled: use DWM // 3) Otherwise use GDI (Screen might be also okay but might lose content) if (isAutoMode) { if (conf.IECapture && windowToCapture.ClassName == "IEFrame") { try { ICapture ieCapture = IECaptureHelper.CaptureIE(captureForWindow); if (ieCapture != null) { return(ieCapture); } } catch (Exception ex) { LOG.WarnFormat("Problem capturing IE, skipping to normal capture. Exception message was: {0}", ex.Message); } } // Take default screen windowCaptureMode = WindowCaptureMode.Screen; // Change to GDI, if allowed if (conf.isGDIAllowed(process)) { if (!dwmEnabled && isWPF(process)) { // do not use GDI, as DWM is not enabled and the application uses PresentationFramework.dll -> isWPF LOG.InfoFormat("Not using GDI for windows of process {0}, as the process uses WPF", process.ProcessName); } else { windowCaptureMode = WindowCaptureMode.GDI; } } // Change to DWM, if enabled and allowed if (dwmEnabled) { if (conf.isDWMAllowed(process)) { windowCaptureMode = WindowCaptureMode.Aero; } } } else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) { if (!dwmEnabled || !conf.isDWMAllowed(process)) { // Take default screen windowCaptureMode = WindowCaptureMode.Screen; // Change to GDI, if allowed if (conf.isGDIAllowed(process)) { windowCaptureMode = WindowCaptureMode.GDI; } } } else if (windowCaptureMode == WindowCaptureMode.GDI && !conf.isGDIAllowed(process)) { // GDI not allowed, take screen windowCaptureMode = WindowCaptureMode.Screen; } LOG.InfoFormat("Capturing window with mode {0}", windowCaptureMode); bool captureTaken = false; // Try to capture while (!captureTaken) { if (windowCaptureMode == WindowCaptureMode.GDI) { ICapture tmpCapture = null; if (conf.isGDIAllowed(process)) { tmpCapture = windowToCapture.CaptureWindow(captureForWindow); } if (tmpCapture != null) { captureForWindow = tmpCapture; captureTaken = true; } else { // A problem, try Screen windowCaptureMode = WindowCaptureMode.Screen; } } else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) { ICapture tmpCapture = null; if (conf.isDWMAllowed(process)) { tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode); } if (tmpCapture != null) { captureForWindow = tmpCapture; captureTaken = true; } else { // A problem, try GDI windowCaptureMode = WindowCaptureMode.GDI; } } else { // Screen capture windowRectangle.Intersect(captureForWindow.ScreenBounds); try { captureForWindow = WindowCapture.CaptureRectangle(captureForWindow, windowRectangle); captureTaken = true; } catch (Exception e) { LOG.Error("Problem capturing", e); return(null); } } } if (captureForWindow != null && windowToCapture != null) { captureForWindow.CaptureDetails.Title = windowToCapture.Text; ((Bitmap)captureForWindow.Image).SetResolution(captureForWindow.CaptureDetails.DpiX, captureForWindow.CaptureDetails.DpiY); } return(captureForWindow); }
/// <summary> /// Capture the supplied Window /// </summary> /// <param name="windowToCapture">Window to capture</param> /// <param name="captureForWindow">The capture to store the details</param> /// <param name="windowCaptureMode">What WindowCaptureMode to use</param> /// <returns></returns> public static ICapture CaptureWindow(WindowDetails windowToCapture, ICapture captureForWindow, WindowCaptureMode windowCaptureMode) { if (captureForWindow == null) { captureForWindow = new Capture(); } Rectangle windowRectangle = windowToCapture.ClientRectangle; if (windowToCapture.Iconic) { // Restore the window making sure it's visible! windowToCapture.Restore(); } // When Vista & DWM (Aero) enabled bool dwmEnabled = DWM.isDWMEnabled(); // For WindowCaptureMode.Auto we check: // 1) Is window IE, use IE Capture // 2) Is Windows >= Vista & DWM enabled: use DWM // 3) Otherwise use GDI (Screen might be also okay but might lose content) if (windowCaptureMode == WindowCaptureMode.Auto) { if (conf.IECapture && windowToCapture.ClassName == "IEFrame") { try { ICapture ieCapture = IECaptureHelper.CaptureIE(captureForWindow); if (ieCapture != null) { return ieCapture; } } catch (Exception ex) { LOG.WarnFormat("Problem capturing IE, skipping to normal capture. Exception message was: {0}", ex.Message); } } // Take default GDI windowCaptureMode = WindowCaptureMode.GDI; // Take DWM if enabled if (dwmEnabled) { windowCaptureMode = WindowCaptureMode.Aero; } } else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) { if (!dwmEnabled) { windowCaptureMode = WindowCaptureMode.GDI; } } LOG.DebugFormat("Capturing window with mode {0}", windowCaptureMode); switch (windowCaptureMode) { case WindowCaptureMode.GDI: // GDI captureForWindow = windowToCapture.CaptureWindow(captureForWindow); break; case WindowCaptureMode.Aero: case WindowCaptureMode.AeroTransparent: // DWM captureForWindow = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode); break; case WindowCaptureMode.Screen: default: // Screen capture windowRectangle.Intersect(captureForWindow.ScreenBounds); try { captureForWindow = WindowCapture.CaptureRectangle(captureForWindow, windowRectangle); } catch (Exception e) { LOG.Error("Problem capturing", e); return null; } break; } captureForWindow.CaptureDetails.Title = windowToCapture.Text; ((Bitmap)captureForWindow.Image).SetResolution(captureForWindow.CaptureDetails.DpiX, captureForWindow.CaptureDetails.DpiY); return captureForWindow; }
/// <summary> /// Capture the supplied Window /// </summary> /// <param name="windowToCapture">Window to capture</param> /// <param name="captureForWindow">The capture to store the details</param> /// <param name="windowCaptureMode">What WindowCaptureMode to use</param> /// <returns></returns> public static ICapture CaptureWindow(WindowDetails windowToCapture, ICapture captureForWindow, WindowCaptureMode windowCaptureMode) { if (captureForWindow == null) { captureForWindow = new Capture(); } Rectangle windowRectangle = windowToCapture.WindowRectangle; if (windowToCapture.Iconic) { // Restore the window making sure it's visible! windowToCapture.Restore(); } // When Vista & DWM (Aero) enabled bool dwmEnabled = DWM.isDWMEnabled(); // get process name to be able to exclude certain processes from certain capture modes Process process = windowToCapture.Process; bool isAutoMode = windowCaptureMode == WindowCaptureMode.Auto; // For WindowCaptureMode.Auto we check: // 1) Is window IE, use IE Capture // 2) Is Windows >= Vista & DWM enabled: use DWM // 3) Otherwise use GDI (Screen might be also okay but might lose content) if (isAutoMode) { if (conf.IECapture && windowToCapture.ClassName == "IEFrame") { try { ICapture ieCapture = IECaptureHelper.CaptureIE(captureForWindow); if (ieCapture != null) { return ieCapture; } } catch (Exception ex) { LOG.WarnFormat("Problem capturing IE, skipping to normal capture. Exception message was: {0}", ex.Message); } } // Take default screen windowCaptureMode = WindowCaptureMode.Screen; // Change to GDI, if allowed if (conf.isGDIAllowed(process)) { if (!dwmEnabled && isWPF(process)) { // do not use GDI, as DWM is not enabled and the application uses PresentationFramework.dll -> isWPF LOG.InfoFormat("Not using GDI for windows of process {0}, as the process uses WPF", process.ProcessName); } else { windowCaptureMode = WindowCaptureMode.GDI; } } // Change to DWM, if enabled and allowed if (dwmEnabled) { if (conf.isDWMAllowed(process)) { windowCaptureMode = WindowCaptureMode.Aero; } } } else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) { if (!dwmEnabled || !conf.isDWMAllowed(process)) { // Take default screen windowCaptureMode = WindowCaptureMode.Screen; // Change to GDI, if allowed if (conf.isGDIAllowed(process)) { windowCaptureMode = WindowCaptureMode.GDI; } } } else if (windowCaptureMode == WindowCaptureMode.GDI && !conf.isGDIAllowed(process)) { // GDI not allowed, take screen windowCaptureMode = WindowCaptureMode.Screen; } LOG.InfoFormat("Capturing window with mode {0}", windowCaptureMode); bool captureTaken = false; // Try to capture while (!captureTaken) { if (windowCaptureMode == WindowCaptureMode.GDI) { ICapture tmpCapture = null; if (conf.isGDIAllowed(process)) { tmpCapture = windowToCapture.CaptureWindow(captureForWindow); } if (tmpCapture != null) { captureForWindow = tmpCapture; captureTaken = true; } else { // A problem, try Screen windowCaptureMode = WindowCaptureMode.Screen; } } else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) { ICapture tmpCapture = null; if (conf.isDWMAllowed(process)) { tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode); } if (tmpCapture != null) { captureForWindow = tmpCapture; captureTaken = true; } else { // A problem, try GDI windowCaptureMode = WindowCaptureMode.GDI; } } else { // Screen capture windowRectangle.Intersect(captureForWindow.ScreenBounds); try { captureForWindow = WindowCapture.CaptureRectangle(captureForWindow, windowRectangle); captureTaken = true; } catch (Exception e) { LOG.Error("Problem capturing", e); return null; } } } if (captureForWindow != null && windowToCapture != null) { captureForWindow.CaptureDetails.Title = windowToCapture.Text; ((Bitmap)captureForWindow.Image).SetResolution(captureForWindow.CaptureDetails.DpiX, captureForWindow.CaptureDetails.DpiY); } return captureForWindow; }