private async Task PrepareNewCapture() { if (_capture != null) { await _capture.Dispose(); } if (UserSettings.All.UseDesktopDuplication) { //Check if Windows 8 or newer. if (!Util.Other.IsWin8OrHigher()) { throw new Exception(LocalizationHelper.Get("S.Recorder.Warning.Windows8")); } //Check if SharpDx is available. if (!Util.Other.IsSharpDxPresent()) { throw new Exception(LocalizationHelper.Get("S.Recorder.Warning.MissingSharpDx")); } Util.Other.LoadSharpDx(); _capture = GetDirectCapture(); } else { //Capture with BitBlt. _capture = UserSettings.All.UseMemoryCache ? new CachedCapture() : new ImageCapture(); } _capture.OnError += exception => { Dispatcher?.Invoke(async() => { //Pause the recording and show the error. await RecordPause(); ErrorDialog.Ok("ScreenToGif", LocalizationHelper.Get("S.Recorder.Warning.CaptureNotPossible"), exception.Message, exception); }); }; var dpi = Monitor.AllMonitors.FirstOrDefault(f => f.IsPrimary)?.Dpi ?? 96d; _capture.Start(1000 / FpsIntegerUpDown.Value, _left, _top, _width, _height, dpi / 96d, Project); }
private void PrepareNewCapture() { _capture?.Dispose(); if (UserSettings.All.UseDesktopDuplication) { //Check if Windows 8 or newer. if (!Util.Other.IsWin8OrHigher()) { throw new Exception(LocalizationHelper.Get("S.Recorder.Warning.Windows8")); } //Check if SharpDx is available. if (!Util.Other.IsSharpDxPresent()) { throw new Exception(LocalizationHelper.Get("S.Recorder.Warning.MissingSharpDx")); } _capture = UserSettings.All.UseMemoryCache ? new DirectCachedCapture() : new DirectImageCapture(); } else { //Capture with BitBlt. _capture = UserSettings.All.UseMemoryCache ? new CachedCapture() : new ImageCapture(); } _capture.OnError += exception => { //Pause the recording and show the error. RecordPause(); ErrorDialog.Ok("ScreenToGif", LocalizationHelper.Get("S.Recorder.Warning.CaptureNotPossible"), exception.Message, exception); }; _capture.Start(1000 / FpsIntegerUpDown.Value, _left, _top, _width, _height, 96 * _scale, Project); }
private void HandleCapture() { // Flag to see if the image was "exported" so the FileEditor doesn't // ask to save the file as long as nothing is done. bool outputMade = false; // Make sure the user sees that the capture is made if (capture.CaptureDetails.CaptureMode == CaptureMode.File || capture.CaptureDetails.CaptureMode == CaptureMode.Clipboard) { // Maybe not "made" but the original is still there... somehow outputMade = true; } else { DoCaptureFeedback(); } LOG.Debug("A capture of: " + capture.CaptureDetails.Title); // check if someone has passed a destination if (capture.CaptureDetails.CaptureDestinations == null || capture.CaptureDetails.CaptureDestinations.Count == 0) { AddConfiguredDestination(); } // Create Surface with capture, this way elements can be added automatically (like the mouse cursor) Surface surface = new Surface(capture); surface.Modified = !outputMade; // Let the processors do their job foreach (IProcessor processor in ProcessorHelper.GetAllProcessors()) { if (processor.isActive) { LOG.InfoFormat("Calling processor {0}", processor.Description); processor.ProcessCapture(surface, capture.CaptureDetails); } } // As the surfaces copies the reference to the image, make sure the image is not being disposed (a trick to save memory) capture.Image = null; // Get CaptureDetails as we need it even after the capture is disposed ICaptureDetails captureDetails = capture.CaptureDetails; bool canDisposeSurface = true; if (captureDetails.HasDestination(Destinations.PickerDestination.DESIGNATION)) { DestinationHelper.ExportCapture(false, Destinations.PickerDestination.DESIGNATION, surface, captureDetails); captureDetails.CaptureDestinations.Clear(); canDisposeSurface = false; } // Disable capturing captureMode = CaptureMode.None; // Dispose the capture, we don't need it anymore (the surface copied all information and we got the title (if any)). capture.Dispose(); capture = null; int destinationCount = captureDetails.CaptureDestinations.Count; if (destinationCount > 0) { // Flag to detect if we need to create a temp file for the email // or use the file that was written foreach (IDestination destination in captureDetails.CaptureDestinations) { if (PickerDestination.DESIGNATION.Equals(destination.Designation)) { continue; } LOG.InfoFormat("Calling destination {0}", destination.Description); bool destinationOk = destination.ExportCapture(false, surface, captureDetails); if (Destinations.EditorDestination.DESIGNATION.Equals(destination.Designation) && destinationOk) { canDisposeSurface = false; } } } if (canDisposeSurface) { surface.Dispose(); } }
/// <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(); } }