/// <summary> /// Start the capture /// </summary> /// <returns>Bitmap</returns> public Bitmap Capture() { if (_windowScroller.NeedsFocus()) { User32Api.SetForegroundWindow(_windowScroller.ScrollBarWindow.Handle); Application.DoEvents(); Thread.Sleep(Delay); Application.DoEvents(); } // Find the area which is scrolling // 1. Take the client bounds var clientBounds = _windowScroller.ScrollBarWindow.GetInfo().ClientBounds; // Use a region for steps 2 and 3 using (var region = new Region(clientBounds)) { // 2. exclude the children, if any foreach (var interopWindow in _windowScroller.ScrollBarWindow.GetChildren()) { region.Exclude(interopWindow.GetInfo().Bounds); } // 3. exclude the scrollbar, if it can be found if (_windowScroller.ScrollBar.HasValue) { region.Exclude(_windowScroller.ScrollBar.Value.Bounds); } // Get the bounds of the region using (var screenGraphics = Graphics.FromHwnd(User32Api.GetDesktopWindow())) { var rectangleF = region.GetBounds(screenGraphics); clientBounds = new NativeRect((int)rectangleF.X, (int)rectangleF.Y, (int)rectangleF.Width, (int)rectangleF.Height); } } if (clientBounds.Width * clientBounds.Height <= 0) { return(null); } // Move the window to the start _windowScroller.Start(); // Register a keyboard hook to make it possible to ESC the capturing var breakScroll = false; var keyboardHook = KeyboardHook.KeyboardEvents .Where(args => args.Key == VirtualKeyCodes.ESCAPE) .Subscribe(args => { args.Handled = true; breakScroll = true; }); Bitmap resultImage = null; try { // A delay to make the window move Application.DoEvents(); Thread.Sleep(Delay); Application.DoEvents(); if (_windowScroller.IsAtStart) { using (var bitmapStitcher = new BitmapStitcher()) { bitmapStitcher.AddBitmap(WindowCapture.CaptureRectangle(clientBounds)); // Loop as long as we are not at the end yet while (!_windowScroller.IsAtEnd && !breakScroll) { // Next "page" _windowScroller.Next(); // Wait a bit, so the window can update Application.DoEvents(); Thread.Sleep(Delay); Application.DoEvents(); // Capture inside loop bitmapStitcher.AddBitmap(WindowCapture.CaptureRectangle(clientBounds)); } resultImage = bitmapStitcher.Result(); } } else { resultImage = WindowCapture.CaptureRectangle(clientBounds); } } catch (Exception ex) { Log.Error().WriteLine(ex); } finally { // Remove hook for escape keyboardHook.Dispose(); // Try to reset location _windowScroller.Reset(); } return(resultImage); }
/// <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.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 (CoreConfig.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(false); } 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) { captureForWindow.CaptureDetails.Title = windowToCapture.Text; } return(captureForWindow); }
/// <summary> /// Make Capture with specified destinations /// </summary> private void MakeCapture() { // Experimental code if (screenCapture != null) { screenCapture.Stop(); screenCapture = null; return; } LOG.Debug(String.Format("Capturing with mode {0} and using Cursor {1}", captureMode, captureMouseCursor)); capture.CaptureDetails.CaptureMode = captureMode; // Get the windows details in a seperate thread windowDetailsThread = PrepareForCaptureWithFeedback(); // Add destinations if no-one passed a handler if (capture.CaptureDetails.CaptureDestinations == null || capture.CaptureDetails.CaptureDestinations.Count == 0) { AddConfiguredDestination(); } // Workaround for proble with DPI retrieval, the FromHwnd activates the window... WindowDetails previouslyActiveWindow = WindowDetails.GetActiveWindow(); // Workaround for changed DPI settings in Windows 7 using (Graphics graphics = Graphics.FromHwnd(MainForm.instance.Handle)) { capture.CaptureDetails.DpiX = graphics.DpiX; capture.CaptureDetails.DpiY = graphics.DpiY; } if (previouslyActiveWindow != null) { // Set previouslyActiveWindow as foreground window previouslyActiveWindow.ToForeground(); } // Delay for the Context menu if (conf.CaptureDelay > 0) { System.Threading.Thread.Sleep(conf.CaptureDelay); } else { conf.CaptureDelay = 0; } // Allways capture Mousecursor, only show when needed capture = WindowCapture.CaptureCursor(capture); capture.CursorVisible = false; // Check if needed if (captureMouseCursor && captureMode != CaptureMode.Clipboard && captureMode != CaptureMode.File) { capture.CursorVisible = conf.CaptureMousepointer; } switch (captureMode) { case CaptureMode.Window: capture = WindowCapture.CaptureScreen(capture); capture.CaptureDetails.AddMetaData("source", "Screen"); CaptureWithFeedback(); break; case CaptureMode.ActiveWindow: if (CaptureActiveWindow()) { if (windowDetailsThread != null) { windowDetailsThread.Join(); } // Capture worked, offset mouse according to screen bounds and capture location capture.MoveMouseLocation(capture.ScreenBounds.Location.X - capture.Location.X, capture.ScreenBounds.Location.Y - capture.Location.Y); capture.MoveElements(capture.ScreenBounds.Location.X - capture.Location.X, capture.ScreenBounds.Location.Y - capture.Location.Y); capture.CaptureDetails.AddMetaData("source", "Window"); } else { captureMode = CaptureMode.FullScreen; capture = WindowCapture.CaptureScreen(capture); capture.CaptureDetails.AddMetaData("source", "Screen"); capture.CaptureDetails.Title = "Screen"; } HandleCapture(); break; case CaptureMode.IE: if (IECaptureHelper.CaptureIE(capture) != null) { capture.CaptureDetails.AddMetaData("source", "Internet Explorer"); HandleCapture(); } break; case CaptureMode.FullScreen: // Check how we need to capture the screen bool captureTaken = false; switch (screenCaptureMode) { case ScreenCaptureMode.Auto: Point mouseLocation = WindowCapture.GetCursorLocation(); foreach (Screen screen in Screen.AllScreens) { if (screen.Bounds.Contains(mouseLocation)) { capture = WindowCapture.CaptureRectangle(capture, screen.Bounds); captureTaken = true; break; } } break; case ScreenCaptureMode.Fixed: if (conf.ScreenToCapture > 0 && conf.ScreenToCapture <= Screen.AllScreens.Length) { capture = WindowCapture.CaptureRectangle(capture, Screen.AllScreens[conf.ScreenToCapture].Bounds); captureTaken = true; } break; case ScreenCaptureMode.FullScreen: // Do nothing, we take the fullscreen capture automatically break; } if (!captureTaken) { capture = WindowCapture.CaptureScreen(capture); } HandleCapture(); break; case CaptureMode.Clipboard: Image clipboardImage = null; string text = "Clipboard"; if (ClipboardHelper.ContainsImage()) { clipboardImage = ClipboardHelper.GetImage(); } if (clipboardImage != null) { if (capture != null) { capture.Image = clipboardImage; } else { capture = new Capture(clipboardImage); } string title = ClipboardHelper.GetText(); if (title == null || title.Trim().Length == 0) { title = "Clipboard"; } capture.CaptureDetails.Title = title; capture.CaptureDetails.AddMetaData("source", "Clipboard"); // Force Editor, keep picker if (capture.CaptureDetails.HasDestination(Destinations.PickerDestination.DESIGNATION)) { capture.CaptureDetails.ClearDestinations(); capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(Destinations.EditorDestination.DESIGNATION)); capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(Destinations.PickerDestination.DESIGNATION)); } else { capture.CaptureDetails.ClearDestinations(); capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(Destinations.EditorDestination.DESIGNATION)); } HandleCapture(); } else { MessageBox.Show("Couldn't create bitmap from : " + text); } break; case CaptureMode.File: Bitmap fileBitmap = null; string filename = capture.CaptureDetails.Filename; if (!string.IsNullOrEmpty(filename)) { try { fileBitmap = ImageHelper.LoadBitmap(filename); } catch (Exception e) { LOG.Error(e.Message, e); MessageBox.Show(Language.GetFormattedString(LangKey.error_openfile, filename)); } } if (fileBitmap != null) { capture.CaptureDetails.Title = Path.GetFileNameWithoutExtension(filename); capture.CaptureDetails.AddMetaData("file", filename); capture.CaptureDetails.AddMetaData("source", "file"); if (capture != null) { capture.Image = fileBitmap; } else { capture = new Capture(fileBitmap); } // Force Editor, keep picker, this is currently the only usefull destination if (capture.CaptureDetails.HasDestination(PickerDestination.DESIGNATION)) { capture.CaptureDetails.ClearDestinations(); capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION)); capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(PickerDestination.DESIGNATION)); } else { capture.CaptureDetails.ClearDestinations(); capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION)); } HandleCapture(); } break; case CaptureMode.LastRegion: if (!RuntimeConfig.LastCapturedRegion.IsEmpty) { capture = WindowCapture.CaptureRectangle(capture, RuntimeConfig.LastCapturedRegion); if (windowDetailsThread != null) { windowDetailsThread.Join(); } capture.CaptureDetails.AddMetaData("source", "screen"); HandleCapture(); } break; case CaptureMode.Region: // Check if a region is pre-supplied! if (Rectangle.Empty.Equals(captureRect)) { capture = WindowCapture.CaptureScreen(capture); capture.CaptureDetails.AddMetaData("source", "screen"); CaptureWithFeedback(); } else { capture = WindowCapture.CaptureRectangle(capture, captureRect); capture.CaptureDetails.AddMetaData("source", "screen"); HandleCapture(); } break; case CaptureMode.Video: capture = WindowCapture.CaptureScreen(capture); // Set the capturemode to be window captureMode = CaptureMode.Window; capture.CaptureDetails.AddMetaData("source", "Video"); CaptureWithFeedback(); break; default: LOG.Warn("Unknown capture mode: " + captureMode); break; } if (windowDetailsThread != null) { windowDetailsThread.Join(); } if (capture != null) { LOG.Debug("Disposing capture"); capture.Dispose(); } }
/// <summary> /// Make Capture with specified destinations /// </summary> private void MakeCapture() { Thread retrieveWindowDetailsThread = null; // This fixes a problem when a balloon is still visible and a capture needs to be taken // forcefully removes the balloon! if (!CoreConfig.HideTrayicon) { MainForm.Instance.NotifyIcon.Visible = false; MainForm.Instance.NotifyIcon.Visible = true; } Log.Debug($"Capturing with mode {_captureMode} and using Cursor {_captureMouseCursor}"); _capture.CaptureDetails.CaptureMode = _captureMode; // Get the windows details in a seperate thread, only for those captures that have a Feedback // As currently the "elements" aren't used, we don't need them yet switch (_captureMode) { case CaptureMode.Region: // Check if a region is pre-supplied! if (Rectangle.Empty.Equals(_captureRect)) { retrieveWindowDetailsThread = PrepareForCaptureWithFeedback(); } break; case CaptureMode.Window: retrieveWindowDetailsThread = PrepareForCaptureWithFeedback(); break; } // Add destinations if no-one passed a handler if (_capture.CaptureDetails.CaptureDestinations == null || _capture.CaptureDetails.CaptureDestinations.Count == 0) { AddConfiguredDestination(); } // Delay for the Context menu if (CoreConfig.CaptureDelay > 0) { Thread.Sleep(CoreConfig.CaptureDelay); } else { CoreConfig.CaptureDelay = 0; } // Capture Mousecursor if we are not loading from file or clipboard, only show when needed if (_captureMode != CaptureMode.File && _captureMode != CaptureMode.Clipboard) { _capture = WindowCapture.CaptureCursor(_capture); _capture.CursorVisible = _captureMouseCursor && CoreConfig.CaptureMousepointer; } switch (_captureMode) { case CaptureMode.Window: _capture = WindowCapture.CaptureScreen(_capture); _capture.CaptureDetails.AddMetaData("source", "Screen"); SetDpi(); CaptureWithFeedback(); break; case CaptureMode.ActiveWindow: if (CaptureActiveWindow()) { // Capture worked, offset mouse according to screen bounds and capture location _capture.MoveMouseLocation(_capture.ScreenBounds.Location.X - _capture.Location.X, _capture.ScreenBounds.Location.Y - _capture.Location.Y); _capture.CaptureDetails.AddMetaData("source", "Window"); } else { _captureMode = CaptureMode.FullScreen; _capture = WindowCapture.CaptureScreen(_capture); _capture.CaptureDetails.AddMetaData("source", "Screen"); _capture.CaptureDetails.Title = "Screen"; } SetDpi(); HandleCapture(); break; case CaptureMode.IE: if (IeCaptureHelper.CaptureIe(_capture, SelectedCaptureWindow) != null) { _capture.CaptureDetails.AddMetaData("source", "Internet Explorer"); SetDpi(); HandleCapture(); } break; case CaptureMode.FullScreen: // Check how we need to capture the screen bool captureTaken = false; switch (_screenCaptureMode) { case ScreenCaptureMode.Auto: Point mouseLocation = User32.GetCursorLocation(); foreach (Screen screen in Screen.AllScreens) { if (screen.Bounds.Contains(mouseLocation)) { _capture = WindowCapture.CaptureRectangle(_capture, screen.Bounds); captureTaken = true; break; } } break; case ScreenCaptureMode.Fixed: if (CoreConfig.ScreenToCapture > 0 && CoreConfig.ScreenToCapture <= Screen.AllScreens.Length) { _capture = WindowCapture.CaptureRectangle(_capture, Screen.AllScreens[CoreConfig.ScreenToCapture].Bounds); captureTaken = true; } break; case ScreenCaptureMode.FullScreen: // Do nothing, we take the fullscreen capture automatically break; } if (!captureTaken) { _capture = WindowCapture.CaptureScreen(_capture); } SetDpi(); HandleCapture(); break; case CaptureMode.Clipboard: Image clipboardImage = ClipboardHelper.GetImage(); if (clipboardImage != null) { if (_capture != null) { _capture.Image = clipboardImage; } else { _capture = new Capture(clipboardImage); } _capture.CaptureDetails.Title = "Clipboard"; _capture.CaptureDetails.AddMetaData("source", "Clipboard"); // Force Editor, keep picker if (_capture.CaptureDetails.HasDestination(PickerDestination.DESIGNATION)) { _capture.CaptureDetails.ClearDestinations(); _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION)); _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(PickerDestination.DESIGNATION)); } else { _capture.CaptureDetails.ClearDestinations(); _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION)); } HandleCapture(); } else { MessageBox.Show(Language.GetString("clipboard_noimage")); } break; case CaptureMode.File: Image fileImage = null; string filename = _capture.CaptureDetails.Filename; if (!string.IsNullOrEmpty(filename)) { try { if (filename.ToLower().EndsWith("." + OutputFormat.greenshot)) { ISurface surface = new Surface(); surface = ImageOutput.LoadGreenshotSurface(filename, surface); surface.CaptureDetails = _capture.CaptureDetails; DestinationHelper.GetDestination(EditorDestination.DESIGNATION).ExportCapture(true, surface, _capture.CaptureDetails); break; } } catch (Exception e) { Log.Error(e.Message, e); MessageBox.Show(Language.GetFormattedString(LangKey.error_openfile, filename)); } try { fileImage = ImageHelper.LoadImage(filename); } catch (Exception e) { Log.Error(e.Message, e); MessageBox.Show(Language.GetFormattedString(LangKey.error_openfile, filename)); } } if (fileImage != null) { _capture.CaptureDetails.Title = Path.GetFileNameWithoutExtension(filename); _capture.CaptureDetails.AddMetaData("file", filename); _capture.CaptureDetails.AddMetaData("source", "file"); if (_capture != null) { _capture.Image = fileImage; } else { _capture = new Capture(fileImage); } // Force Editor, keep picker, this is currently the only usefull destination if (_capture.CaptureDetails.HasDestination(PickerDestination.DESIGNATION)) { _capture.CaptureDetails.ClearDestinations(); _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION)); _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(PickerDestination.DESIGNATION)); } else { _capture.CaptureDetails.ClearDestinations(); _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION)); } HandleCapture(); } break; case CaptureMode.LastRegion: if (!CoreConfig.LastCapturedRegion.IsEmpty) { _capture = WindowCapture.CaptureRectangle(_capture, CoreConfig.LastCapturedRegion); // TODO: Reactive / check if the elements code is activated //if (windowDetailsThread != null) { // windowDetailsThread.Join(); //} // Set capture title, fixing bug #3569703 foreach (WindowDetails window in WindowDetails.GetVisibleWindows()) { Point estimatedLocation = new Point(CoreConfig.LastCapturedRegion.X + CoreConfig.LastCapturedRegion.Width / 2, CoreConfig.LastCapturedRegion.Y + CoreConfig.LastCapturedRegion.Height / 2); if (window.Contains(estimatedLocation)) { _selectedCaptureWindow = window; _capture.CaptureDetails.Title = _selectedCaptureWindow.Text; break; } } // Move cursor, fixing bug #3569703 _capture.MoveMouseLocation(_capture.ScreenBounds.Location.X - _capture.Location.X, _capture.ScreenBounds.Location.Y - _capture.Location.Y); //capture.MoveElements(capture.ScreenBounds.Location.X - capture.Location.X, capture.ScreenBounds.Location.Y - capture.Location.Y); _capture.CaptureDetails.AddMetaData("source", "screen"); SetDpi(); HandleCapture(); } break; case CaptureMode.Region: // Check if a region is pre-supplied! if (Rectangle.Empty.Equals(_captureRect)) { _capture = WindowCapture.CaptureScreen(_capture); _capture.CaptureDetails.AddMetaData("source", "screen"); SetDpi(); CaptureWithFeedback(); } else { _capture = WindowCapture.CaptureRectangle(_capture, _captureRect); _capture.CaptureDetails.AddMetaData("source", "screen"); SetDpi(); HandleCapture(); } break; default: Log.Warn("Unknown capture mode: " + _captureMode); break; } // Wait for thread, otherwise we can't dipose the CaptureHelper retrieveWindowDetailsThread?.Join(); if (_capture != null) { Log.Debug("Disposing capture"); _capture.Dispose(); } }