/// <summary> /// Here the logic for capturing the IE Content is located /// </summary> /// <param name="capture">ICapture where the capture needs to be stored</param> /// <param name="windowToCapture">window to use</param> /// <returns>ICapture with the content (if any)</returns> public static ICapture CaptureIE(ICapture capture, WindowDetails windowToCapture) { if (windowToCapture == null) { windowToCapture = WindowDetails.GetActiveWindow(); } // Show backgroundform after retrieving the active window.. BackgroundForm backgroundForm = new BackgroundForm(Language.GetString(LangKey.contextmenu_captureie), Language.GetString(LangKey.wait_ie_capture)); backgroundForm.Show(); //BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(language.GetString(LangKey.contextmenu_captureie), language.GetString(LangKey.wait_ie_capture)); try { //Get IHTMLDocument2 for the current active window DocumentContainer documentContainer = CreateDocumentContainer(windowToCapture); // Nothing found if (documentContainer == null) { LOG.Debug("Nothing to capture found"); return(null); } try { LOG.DebugFormat("Window class {0}", documentContainer.ContentWindow.ClassName); LOG.DebugFormat("Window location {0}", documentContainer.ContentWindow.Location); } catch (Exception ex) { LOG.Warn("Error while logging information.", ex); } // bitmap to return Bitmap returnBitmap = null; Size pageSize = Size.Empty; try { pageSize = PrepareCapture(documentContainer, capture); returnBitmap = capturePage(documentContainer, capture, pageSize); } catch (Exception captureException) { LOG.Error("Exception found, ignoring and returning nothing! Error was: ", captureException); } // TODO: Enable when the elements are usable again. // Capture the element on the page //try { // if (configuration.IEFieldCapture && capture.CaptureDetails.HasDestination("Editor")) { // // clear the current elements, as they are for the window itself // capture.Elements.Clear(); // CaptureElement documentCaptureElement = documentContainer.CreateCaptureElements(pageSize); // foreach(DocumentContainer frameDocument in documentContainer.Frames) { // try { // CaptureElement frameCaptureElement = frameDocument.CreateCaptureElements(Size.Empty); // if (frameCaptureElement != null) { // documentCaptureElement.Children.Add(frameCaptureElement); // } // } catch (Exception ex) { // LOG.Warn("An error occurred while creating the capture elements: ", ex); // } // } // capture.AddElement(documentCaptureElement); // // Offset the elements, as they are "back offseted" later... // Point windowLocation = documentContainer.ContentWindow.WindowRectangle.Location; // capture.MoveElements(-(capture.ScreenBounds.Location.X-windowLocation.X), -(capture.ScreenBounds.Location.Y-windowLocation.Y)); // } //} catch (Exception elementsException) { // LOG.Warn("An error occurred while creating the capture elements: ", elementsException); //} if (returnBitmap == null) { return(null); } // Store the bitmap for further processing capture.Image = returnBitmap; try { // Store the location of the window capture.Location = documentContainer.ContentWindow.Location; // The URL is available unter "document2.url" and can be used to enhance the meta-data etc. capture.CaptureDetails.AddMetaData("url", documentContainer.Url); // Store the title of the page if (documentContainer.Name != null) { capture.CaptureDetails.Title = documentContainer.Name; } else { capture.CaptureDetails.Title = windowToCapture.Text; } } catch (Exception ex) { LOG.Warn("Problems getting some attributes...", ex); } // Store the URL of the page if (documentContainer.Url != null) { try { Uri uri = new Uri(documentContainer.Url); capture.CaptureDetails.AddMetaData("URL", uri.OriginalString); // As the URL can hardly be used in a filename, the following can be used if (!string.IsNullOrEmpty(uri.Scheme)) { capture.CaptureDetails.AddMetaData("URL_SCHEME", uri.Scheme); } if (!string.IsNullOrEmpty(uri.DnsSafeHost)) { capture.CaptureDetails.AddMetaData("URL_HOSTNAME", uri.DnsSafeHost); } if (!string.IsNullOrEmpty(uri.AbsolutePath)) { capture.CaptureDetails.AddMetaData("URL_PATH", uri.AbsolutePath); } if (!string.IsNullOrEmpty(uri.Query)) { capture.CaptureDetails.AddMetaData("URL_QUERY", uri.Query); } if (!string.IsNullOrEmpty(uri.UserInfo)) { capture.CaptureDetails.AddMetaData("URL_USER", uri.UserInfo); } capture.CaptureDetails.AddMetaData("URL_PORT", uri.Port.ToString()); } catch (Exception e) { LOG.Warn("Exception when trying to use url in metadata " + documentContainer.Url, e); } } try { // Only move the mouse to correct for the capture offset capture.MoveMouseLocation(-documentContainer.ViewportRectangle.X, -documentContainer.ViewportRectangle.Y); // Used to be: capture.MoveMouseLocation(-(capture.Location.X + documentContainer.CaptureOffset.X), -(capture.Location.Y + documentContainer.CaptureOffset.Y)); } catch (Exception ex) { LOG.Warn("Error while correcting the mouse offset.", ex); } } finally { // Always close the background form backgroundForm.CloseDialog(); } return(capture); }
/// <summary> /// Prepare the calculates for all the frames, move and fit... /// </summary> /// <param name="documentContainer"></param> /// <param name="capture"></param> /// <returns>Size of the complete page</returns> private static Size PrepareCapture(DocumentContainer documentContainer, ICapture capture) { // Calculate the page size int pageWidth = documentContainer.ScrollWidth; int pageHeight = documentContainer.ScrollHeight; // Here we loop over all the frames and try to make sure they don't overlap bool movedFrame; do { movedFrame = false; foreach (DocumentContainer currentFrame in documentContainer.Frames) { foreach (DocumentContainer otherFrame in documentContainer.Frames) { if (otherFrame.ID == currentFrame.ID) { continue; } // check if we need to move if (otherFrame.DestinationRectangle.IntersectsWith(currentFrame.DestinationRectangle) && !otherFrame.SourceRectangle.IntersectsWith(currentFrame.SourceRectangle)) { bool horizalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width; bool verticalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width; bool horizalMove = currentFrame.SourceLeft < currentFrame.DestinationLeft; bool verticalMove = currentFrame.SourceTop < currentFrame.DestinationTop; bool leftOf = currentFrame.SourceRight <= otherFrame.SourceLeft; bool belowOf = currentFrame.SourceBottom <= otherFrame.SourceTop; if ((horizalResize || horizalMove) && leftOf) { // Current frame resized horizontally, so move other horizontally LOG.DebugFormat("Moving Frame {0} horizontally to the right of {1}", otherFrame.Name, currentFrame.Name); otherFrame.DestinationLeft = currentFrame.DestinationRight; movedFrame = true; } else if ((verticalResize || verticalMove) && belowOf) { // Current frame resized vertically, so move other vertically LOG.DebugFormat("Moving Frame {0} vertically to the bottom of {1}", otherFrame.Name, currentFrame.Name); otherFrame.DestinationTop = currentFrame.DestinationBottom; movedFrame = true; } else { LOG.DebugFormat("Frame {0} intersects with {1}", otherFrame.Name, currentFrame.Name); } } } } } while(movedFrame); bool movedMouse = false; // Correct cursor location to be inside the window capture.MoveMouseLocation(-documentContainer.ContentWindow.Location.X, -documentContainer.ContentWindow.Location.Y); // See if the page has the correct size, as we capture the full frame content AND might have moved them // the normal pagesize will no longer be enough foreach (DocumentContainer frameData in documentContainer.Frames) { if (!movedMouse && frameData.SourceRectangle.Contains(capture.CursorLocation)) { // Correct mouse cursor location for scrolled position (so it shows on the capture where it really was) capture.MoveMouseLocation(frameData.ScrollLeft, frameData.ScrollTop); movedMouse = true; // Apply any other offset changes int offsetX = frameData.DestinationLocation.X - frameData.SourceLocation.X; int offsetY = frameData.DestinationLocation.Y - frameData.SourceLocation.Y; capture.MoveMouseLocation(offsetX, offsetY); } //Get Frame Width & Height pageWidth = Math.Max(pageWidth, frameData.DestinationRight); pageHeight = Math.Max(pageHeight, frameData.DestinationBottom); } // If the mouse hasn't been moved, it wasn't on a frame. So correct the mouse according to the scroll position of the document if (!movedMouse) { // Correct mouse cursor location capture.MoveMouseLocation(documentContainer.ScrollLeft, documentContainer.ScrollTop); } // Limit the size as the editor currently can't work with sizes > short.MaxValue if (pageWidth > short.MaxValue) { LOG.WarnFormat("Capture has a width of {0} which bigger than the maximum supported {1}, cutting width to the maxium.", pageWidth, short.MaxValue); pageWidth = Math.Min(pageWidth, short.MaxValue); } if (pageHeight > short.MaxValue) { LOG.WarnFormat("Capture has a height of {0} which bigger than the maximum supported {1}, cutting height to the maxium", pageHeight, short.MaxValue); pageHeight = Math.Min(pageHeight, short.MaxValue); } return(new Size(pageWidth, pageHeight)); }
/// <summary> /// Capture the actual page (document) /// </summary> /// <param name="documentContainer">The document wrapped in a container</param> /// <returns>Bitmap with the page content as an image</returns> private static Bitmap capturePage(DocumentContainer documentContainer, ICapture capture) { WindowDetails contentWindowDetails = documentContainer.ContentWindow; // Calculate the page size int pageWidth = documentContainer.ScrollWidth; int pageHeight = documentContainer.ScrollHeight; // Here we loop over all the frames and try to make sure they don't overlap bool movedFrame; do { movedFrame = false; foreach (DocumentContainer currentFrame in documentContainer.Frames) { foreach (DocumentContainer otherFrame in documentContainer.Frames) { if (otherFrame.ID == currentFrame.ID) { continue; } // check if we need to move if (otherFrame.DestinationRectangle.IntersectsWith(currentFrame.DestinationRectangle) && !otherFrame.SourceRectangle.IntersectsWith(currentFrame.SourceRectangle)) { bool horizalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width; bool verticalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width; bool horizalMove = currentFrame.SourceLeft < currentFrame.DestinationLeft; bool verticalMove = currentFrame.SourceTop < currentFrame.DestinationTop; bool leftOf = currentFrame.SourceRight <= otherFrame.SourceLeft; bool belowOf = currentFrame.SourceBottom <= otherFrame.SourceTop; if ((horizalResize || horizalMove) && leftOf) { // Current frame resized horizontally, so move other horizontally LOG.DebugFormat("Moving Frame {0} horizontally to the right of {1}", otherFrame.Name, currentFrame.Name); otherFrame.DestinationLeft = currentFrame.DestinationRight; movedFrame = true; } else if ((verticalResize || verticalMove) && belowOf) { // Current frame resized vertically, so move other vertically LOG.DebugFormat("Moving Frame {0} vertically to the bottom of {1}", otherFrame.Name, currentFrame.Name); otherFrame.DestinationTop = currentFrame.DestinationBottom; movedFrame = true; } else { LOG.DebugFormat("Frame {0} intersects with {1}", otherFrame.Name, currentFrame.Name); } } } } } while(movedFrame); bool movedMouse = false; // Correct cursor location to be inside the window capture.MoveMouseLocation(-documentContainer.ContentWindow.Location.X, -documentContainer.ContentWindow.Location.Y); // See if the page has the correct size, as we capture the full frame content AND might have moved them // the normal pagesize will no longer be enough foreach (DocumentContainer frameData in documentContainer.Frames) { if (!movedMouse && frameData.SourceRectangle.Contains(capture.CursorLocation)) { // Correct mouse cursor location for scrolled position (so it shows on the capture where it really was) capture.MoveMouseLocation(frameData.ScrollLeft, frameData.ScrollTop); movedMouse = true; // Apply any other offset changes int offsetX = frameData.DestinationLocation.X - frameData.SourceLocation.X; int offsetY = frameData.DestinationLocation.Y - frameData.SourceLocation.Y; capture.MoveMouseLocation(offsetX, offsetY); } //Get Frame Width & Height pageWidth = Math.Max(pageWidth, frameData.DestinationRight); pageHeight = Math.Max(pageHeight, frameData.DestinationBottom); } // If the mouse hasn't been moved, it wasn't on a frame. So correct the mouse according to the scroll position of the document if (!movedMouse) { // Correct mouse cursor location capture.MoveMouseLocation(documentContainer.ScrollLeft, documentContainer.ScrollTop); } // Limit the size as the editor currently can't work with sizes > short.MaxValue if (pageWidth > short.MaxValue) { LOG.WarnFormat("Capture has a width of {0} which bigger than the maximum supported {1}, cutting width to the maxium.", pageWidth, short.MaxValue); pageWidth = Math.Min(pageWidth, short.MaxValue); } if (pageHeight > short.MaxValue) { LOG.WarnFormat("Capture has a height of {0} which bigger than the maximum supported {1}, cutting height to the maxium", pageHeight, short.MaxValue); pageHeight = Math.Min(pageHeight, short.MaxValue); } //Create a target bitmap to draw into with the calculated page size Bitmap returnBitmap = new Bitmap(pageWidth, pageHeight, PixelFormat.Format24bppRgb); using (Graphics graphicsTarget = Graphics.FromImage(returnBitmap)) { // Clear the target with the backgroundcolor Color clearColor = documentContainer.BackgroundColor; LOG.DebugFormat("Clear color: {0}", clearColor); graphicsTarget.Clear(clearColor); // Get the base document & draw it drawDocument(documentContainer, contentWindowDetails, graphicsTarget); //ParseElements(documentContainer, graphicsTarget, returnBitmap); // Loop over the frames and clear their source area so we don't see any artefacts foreach (DocumentContainer frameDocument in documentContainer.Frames) { using (Brush brush = new SolidBrush(clearColor)) { graphicsTarget.FillRectangle(brush, frameDocument.SourceRectangle); } } // Loop over the frames and capture their content foreach (DocumentContainer frameDocument in documentContainer.Frames) { drawDocument(frameDocument, contentWindowDetails, graphicsTarget); //ParseElements(frameDocument, graphicsTarget, returnBitmap); } } return(returnBitmap); }
/// <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 (!conf.HideTrayicon) { MainForm.Instance.NotifyIcon.Visible = false; MainForm.Instance.NotifyIcon.Visible = true; } 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, 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 (conf.CaptureDelay > 0) { Thread.Sleep(conf.CaptureDelay); } else { conf.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); if (_captureMouseCursor) { _capture.CursorVisible = conf.CaptureMousepointer; } else { _capture.CursorVisible = false; } } 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 (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); } 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 (!conf.LastCapturedRegion.IsEmpty) { _capture = WindowCapture.CaptureRectangle(_capture, conf.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(conf.LastCapturedRegion.X + (conf.LastCapturedRegion.Width / 2), conf.LastCapturedRegion.Y + (conf.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 if (retrieveWindowDetailsThread != null) { retrieveWindowDetailsThread.Join(); } if (_capture != null) { LOG.Debug("Disposing capture"); _capture.Dispose(); } }
/// <summary> /// Here the logic for capturing the IE Content is located /// </summary> /// <param name="capture">ICapture where the capture needs to be stored</param> /// <returns>ICapture with the content (if any)</returns> public static ICapture CaptureIE(ICapture capture) { WindowDetails activeWindow = WindowDetails.GetActiveWindow(); // Show backgroundform after retrieving the active window.. BackgroundForm backgroundForm = new BackgroundForm(Language.GetString(LangKey.contextmenu_captureie), Language.GetString(LangKey.wait_ie_capture)); backgroundForm.Show(); //BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(language.GetString(LangKey.contextmenu_captureie), language.GetString(LangKey.wait_ie_capture)); try { //Get IHTMLDocument2 for the current active window DocumentContainer documentContainer = GetDocument(activeWindow); // Nothing found if (documentContainer == null) { LOG.Debug("Nothing to capture found"); return null; } LOG.DebugFormat("Window class {0}", documentContainer.ContentWindow.ClassName); LOG.DebugFormat("Window location {0}", documentContainer.ContentWindow.Location); // The URL is available unter "document2.url" and can be used to enhance the meta-data etc. capture.CaptureDetails.AddMetaData("url", documentContainer.Url); // bitmap to return Bitmap returnBitmap = null; Size pageSize = Size.Empty; try { pageSize = PrepareCapture(documentContainer, capture); returnBitmap = capturePage(documentContainer, capture, pageSize); } catch (Exception captureException) { LOG.Error("Exception found, ignoring and returning nothing! Error was: ", captureException); } // Capture the element on the page try { if (configuration.IEFieldCapture && capture.CaptureDetails.HasDestination("Editor")) { // clear the current elements, as they are for the window itself capture.Elements.Clear(); CaptureElement documentCaptureElement = documentContainer.CreateCaptureElements(pageSize); foreach(DocumentContainer frameDocument in documentContainer.Frames) { CaptureElement frameCaptureElement = frameDocument.CreateCaptureElements(Size.Empty); if (frameCaptureElement != null) { documentCaptureElement.Children.Add(frameCaptureElement); } } capture.AddElement(documentCaptureElement); // Offset the elements, as they are "back offseted" later... Point windowLocation = documentContainer.ContentWindow.WindowRectangle.Location; capture.MoveElements(-(capture.ScreenBounds.Location.X-windowLocation.X), -(capture.ScreenBounds.Location.Y-windowLocation.Y)); } } catch (Exception elementsException) { LOG.Warn("An error occurred while creating the capture elements: ", elementsException); } if (returnBitmap == null) { return null; } // Store the bitmap for further processing capture.Image = returnBitmap; // Store the location of the window capture.Location = documentContainer.ContentWindow.Location; // Store the title of the page if (documentContainer.Name != null) { capture.CaptureDetails.Title = documentContainer.Name; } else { capture.CaptureDetails.Title = activeWindow.Text; } // Store the URL of the page if (documentContainer.Url != null) { Uri uri = new Uri(documentContainer.Url); capture.CaptureDetails.AddMetaData("URL", uri.OriginalString); // As the URL can hardly be used in a filename, the following can be used if (!string.IsNullOrEmpty(uri.Scheme)) { capture.CaptureDetails.AddMetaData("URL_SCHEME", uri.Scheme); } if (!string.IsNullOrEmpty(uri.DnsSafeHost)) { capture.CaptureDetails.AddMetaData("URL_HOSTNAME", uri.DnsSafeHost); } if (!string.IsNullOrEmpty(uri.AbsolutePath)) { capture.CaptureDetails.AddMetaData("URL_PATH", uri.AbsolutePath); } if (!string.IsNullOrEmpty(uri.Query)) { capture.CaptureDetails.AddMetaData("URL_QUERY", uri.Query); } if (!string.IsNullOrEmpty(uri.UserInfo)) { capture.CaptureDetails.AddMetaData("URL_USER", uri.UserInfo); } capture.CaptureDetails.AddMetaData("URL_PORT", uri.Port.ToString()); } // Only move the mouse to correct for the capture offset capture.MoveMouseLocation(-documentContainer.ViewportRectangle.X, -documentContainer.ViewportRectangle.Y); // Used to be: capture.MoveMouseLocation(-(capture.Location.X + documentContainer.CaptureOffset.X), -(capture.Location.Y + documentContainer.CaptureOffset.Y)); } finally { // Always close the background form backgroundForm.CloseDialog(); } return capture; }
/// <summary> /// Here the logic for capturing the IE Content is located /// </summary> /// <param name="capture">ICapture where the capture needs to be stored</param> /// <returns>ICapture with the content (if any)</returns> public static ICapture CaptureIE(ICapture capture) { WindowDetails activeWindow = WindowDetails.GetActiveWindow(); // Show backgroundform after retrieving the active window.. BackgroundForm backgroundForm = new BackgroundForm(language.GetString(LangKey.contextmenu_captureie), language.GetString(LangKey.wait_ie_capture)); backgroundForm.Show(); //BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(language.GetString(LangKey.contextmenu_captureie), language.GetString(LangKey.wait_ie_capture)); try { //Get IHTMLDocument2 for the current active window DocumentContainer documentContainer = GetDocument(activeWindow); // Nothing found if (documentContainer == null) { LOG.Debug("Nothing to capture found"); return(null); } LOG.DebugFormat("Window class {0}", documentContainer.ContentWindow.ClassName); LOG.DebugFormat("Window location {0}", documentContainer.ContentWindow.Location); // The URL is available unter "document2.url" and can be used to enhance the meta-data etc. capture.CaptureDetails.AddMetaData("url", documentContainer.Url); // bitmap to return Bitmap returnBitmap = null; try { returnBitmap = capturePage(documentContainer, capture); } catch (Exception e) { LOG.Error("Exception found, ignoring and returning nothing! Error was: ", e); } if (returnBitmap == null) { return(null); } // Store the bitmap for further processing capture.Image = returnBitmap; // Store the location of the window capture.Location = documentContainer.ContentWindow.Location; // Store the title of the Page if (documentContainer.Name != null) { capture.CaptureDetails.Title = documentContainer.Name; } else { capture.CaptureDetails.Title = activeWindow.Text; } // Only move the mouse to correct for the capture offset capture.MoveMouseLocation(-documentContainer.ViewportRectangle.X, -documentContainer.ViewportRectangle.Y); // Used to be: capture.MoveMouseLocation(-(capture.Location.X + documentContainer.CaptureOffset.X), -(capture.Location.Y + documentContainer.CaptureOffset.Y)); } finally { // Always close the background form backgroundForm.CloseDialog(); } return(capture); }
/// <summary> /// Here the logic for capturing the IE Content is located /// </summary> /// <param name="capture">ICapture where the capture needs to be stored</param> /// <returns>ICapture with the content (if any)</returns> public static ICapture CaptureIE(ICapture capture) { WindowDetails activeWindow = WindowDetails.GetActiveWindow(); // Show backgroundform after retrieving the active window.. BackgroundForm backgroundForm = new BackgroundForm(language.GetString(LangKey.contextmenu_captureie), language.GetString(LangKey.wait_ie_capture)); backgroundForm.Show(); //BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(language.GetString(LangKey.contextmenu_captureie), language.GetString(LangKey.wait_ie_capture)); try { //Get IHTMLDocument2 for the current active window DocumentContainer documentContainer = GetDocument(activeWindow); // Nothing found if (documentContainer == null) { LOG.Debug("Nothing to capture found"); return null; } LOG.DebugFormat("Window class {0}", documentContainer.ContentWindow.ClassName); LOG.DebugFormat("Window location {0}", documentContainer.ContentWindow.Location); // The URL is available unter "document2.url" and can be used to enhance the meta-data etc. capture.CaptureDetails.AddMetaData("url", documentContainer.Url); // bitmap to return Bitmap returnBitmap = null; try { returnBitmap = capturePage(documentContainer, capture); } catch (Exception e) { LOG.Error("Exception found, ignoring and returning nothing! Error was: ", e); } if (returnBitmap == null) { return null; } // Store the bitmap for further processing capture.Image = returnBitmap; // Store the location of the window capture.Location = documentContainer.ContentWindow.Location; // Store the title of the Page if (documentContainer.Name != null) { capture.CaptureDetails.Title = documentContainer.Name; } else { capture.CaptureDetails.Title = activeWindow.Text; } // Only move the mouse to correct for the capture offset capture.MoveMouseLocation(-documentContainer.ViewportRectangle.X, -documentContainer.ViewportRectangle.Y); // Used to be: capture.MoveMouseLocation(-(capture.Location.X + documentContainer.CaptureOffset.X), -(capture.Location.Y + documentContainer.CaptureOffset.Y)); } finally { // Always close the background form backgroundForm.CloseDialog(); } return capture; }
/// <summary> /// Prepare the calculates for all the frames, move and fit... /// </summary> /// <param name="documentContainer"></param> /// <param name="capture"></param> /// <returns>Size of the complete page</returns> private static Size PrepareCapture(DocumentContainer documentContainer, ICapture capture) { // Calculate the page size int pageWidth = documentContainer.ScrollWidth; int pageHeight = documentContainer.ScrollHeight; // Here we loop over all the frames and try to make sure they don't overlap bool movedFrame; do { movedFrame = false; foreach(DocumentContainer currentFrame in documentContainer.Frames) { foreach(DocumentContainer otherFrame in documentContainer.Frames) { if (otherFrame.ID == currentFrame.ID) { continue; } // check if we need to move if (otherFrame.DestinationRectangle.IntersectsWith(currentFrame.DestinationRectangle) && !otherFrame.SourceRectangle.IntersectsWith(currentFrame.SourceRectangle)) { bool horizalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width; bool verticalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width; bool horizalMove = currentFrame.SourceLeft < currentFrame.DestinationLeft; bool verticalMove = currentFrame.SourceTop < currentFrame.DestinationTop; bool leftOf = currentFrame.SourceRight <= otherFrame.SourceLeft; bool belowOf = currentFrame.SourceBottom <= otherFrame.SourceTop; if ((horizalResize || horizalMove) && leftOf) { // Current frame resized horizontally, so move other horizontally LOG.DebugFormat("Moving Frame {0} horizontally to the right of {1}", otherFrame.Name, currentFrame.Name); otherFrame.DestinationLeft = currentFrame.DestinationRight; movedFrame = true; } else if ((verticalResize || verticalMove) && belowOf){ // Current frame resized vertically, so move other vertically LOG.DebugFormat("Moving Frame {0} vertically to the bottom of {1}", otherFrame.Name, currentFrame.Name); otherFrame.DestinationTop = currentFrame.DestinationBottom; movedFrame = true; } else { LOG.DebugFormat("Frame {0} intersects with {1}", otherFrame.Name, currentFrame.Name); } } } } } while(movedFrame); bool movedMouse = false; // Correct cursor location to be inside the window capture.MoveMouseLocation(-documentContainer.ContentWindow.Location.X, -documentContainer.ContentWindow.Location.Y); // See if the page has the correct size, as we capture the full frame content AND might have moved them // the normal pagesize will no longer be enough foreach(DocumentContainer frameData in documentContainer.Frames) { if (!movedMouse && frameData.SourceRectangle.Contains(capture.CursorLocation)) { // Correct mouse cursor location for scrolled position (so it shows on the capture where it really was) capture.MoveMouseLocation(frameData.ScrollLeft, frameData.ScrollTop); movedMouse = true; // Apply any other offset changes int offsetX = frameData.DestinationLocation.X - frameData.SourceLocation.X; int offsetY = frameData.DestinationLocation.Y - frameData.SourceLocation.Y; capture.MoveMouseLocation(offsetX, offsetY); } //Get Frame Width & Height pageWidth = Math.Max(pageWidth, frameData.DestinationRight); pageHeight = Math.Max(pageHeight, frameData.DestinationBottom); } // If the mouse hasn't been moved, it wasn't on a frame. So correct the mouse according to the scroll position of the document if (!movedMouse) { // Correct mouse cursor location capture.MoveMouseLocation(documentContainer.ScrollLeft, documentContainer.ScrollTop); } // Limit the size as the editor currently can't work with sizes > short.MaxValue if (pageWidth > short.MaxValue) { LOG.WarnFormat("Capture has a width of {0} which bigger than the maximum supported {1}, cutting width to the maxium.", pageWidth, short.MaxValue); pageWidth = Math.Min(pageWidth, short.MaxValue); } if (pageHeight > short.MaxValue) { LOG.WarnFormat("Capture has a height of {0} which bigger than the maximum supported {1}, cutting height to the maxium", pageHeight, short.MaxValue); pageHeight = Math.Min(pageHeight, short.MaxValue); } return new Size(pageWidth, pageHeight); }
/// <summary> /// Capture the actual page (document) /// </summary> /// <param name="documentContainer">The document wrapped in a container</param> /// <returns>Bitmap with the page content as an image</returns> private static Bitmap capturePage(DocumentContainer documentContainer, ICapture capture) { WindowDetails contentWindowDetails = documentContainer.ContentWindow; // Calculate the page size int pageWidth = documentContainer.ScrollWidth; int pageHeight = documentContainer.ScrollHeight; // Here we loop over all the frames and try to make sure they don't overlap bool movedFrame; do { movedFrame = false; foreach(DocumentContainer currentFrame in documentContainer.Frames) { foreach(DocumentContainer otherFrame in documentContainer.Frames) { if (otherFrame.ID == currentFrame.ID) { continue; } // check if we need to move if (otherFrame.DestinationRectangle.IntersectsWith(currentFrame.DestinationRectangle) && !otherFrame.SourceRectangle.IntersectsWith(currentFrame.SourceRectangle)) { bool horizalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width; bool verticalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width; bool horizalMove = currentFrame.SourceLeft < currentFrame.DestinationLeft; bool verticalMove = currentFrame.SourceTop < currentFrame.DestinationTop; bool leftOf = currentFrame.SourceRight <= otherFrame.SourceLeft; bool belowOf = currentFrame.SourceBottom <= otherFrame.SourceTop; if ((horizalResize || horizalMove) && leftOf) { // Current frame resized horizontally, so move other horizontally LOG.DebugFormat("Moving Frame {0} horizontally to the right of {1}", otherFrame.Name, currentFrame.Name); otherFrame.DestinationLeft = currentFrame.DestinationRight; movedFrame = true; } else if ((verticalResize || verticalMove) && belowOf){ // Current frame resized vertically, so move other vertically LOG.DebugFormat("Moving Frame {0} vertically to the bottom of {1}", otherFrame.Name, currentFrame.Name); otherFrame.DestinationTop = currentFrame.DestinationBottom; movedFrame = true; } else { LOG.DebugFormat("Frame {0} intersects with {1}", otherFrame.Name, currentFrame.Name); } } } } } while(movedFrame); bool movedMouse = false; // Correct cursor location to be inside the window capture.MoveMouseLocation(-documentContainer.ContentWindow.Location.X, -documentContainer.ContentWindow.Location.Y); // See if the page has the correct size, as we capture the full frame content AND might have moved them // the normal pagesize will no longer be enough foreach(DocumentContainer frameData in documentContainer.Frames) { if (!movedMouse && frameData.SourceRectangle.Contains(capture.CursorLocation)) { // Correct mouse cursor location for scrolled position (so it shows on the capture where it really was) capture.MoveMouseLocation(frameData.ScrollLeft, frameData.ScrollTop); movedMouse = true; // Apply any other offset changes int offsetX = frameData.DestinationLocation.X - frameData.SourceLocation.X; int offsetY = frameData.DestinationLocation.Y - frameData.SourceLocation.Y; capture.MoveMouseLocation(offsetX, offsetY); } //Get Frame Width & Height pageWidth = Math.Max(pageWidth, frameData.DestinationRight); pageHeight = Math.Max(pageHeight, frameData.DestinationBottom); } // If the mouse hasn't been moved, it wasn't on a frame. So correct the mouse according to the scroll position of the document if (!movedMouse) { // Correct mouse cursor location capture.MoveMouseLocation(documentContainer.ScrollLeft, documentContainer.ScrollTop); } // Limit the size as the editor currently can't work with sizes > short.MaxValue if (pageWidth > short.MaxValue) { LOG.WarnFormat("Capture has a width of {0} which bigger than the maximum supported {1}, cutting width to the maxium.", pageWidth, short.MaxValue); pageWidth = Math.Min(pageWidth, short.MaxValue); } if (pageHeight > short.MaxValue) { LOG.WarnFormat("Capture has a height of {0} which bigger than the maximum supported {1}, cutting height to the maxium", pageHeight, short.MaxValue); pageHeight = Math.Min(pageHeight, short.MaxValue); } //Create a target bitmap to draw into with the calculated page size Bitmap returnBitmap = new Bitmap(pageWidth, pageHeight, PixelFormat.Format24bppRgb); using (Graphics graphicsTarget = Graphics.FromImage(returnBitmap)) { // Clear the target with the backgroundcolor Color clearColor = documentContainer.BackgroundColor; LOG.DebugFormat("Clear color: {0}", clearColor); graphicsTarget.Clear(clearColor); // Get the base document & draw it drawDocument(documentContainer, contentWindowDetails, graphicsTarget); //ParseElements(documentContainer, graphicsTarget, returnBitmap); // Loop over the frames and clear their source area so we don't see any artefacts foreach(DocumentContainer frameDocument in documentContainer.Frames) { using(Brush brush = new SolidBrush(clearColor)) { graphicsTarget.FillRectangle(brush, frameDocument.SourceRectangle); } } // Loop over the frames and capture their content foreach(DocumentContainer frameDocument in documentContainer.Frames) { drawDocument(frameDocument, contentWindowDetails, graphicsTarget); //ParseElements(frameDocument, graphicsTarget, returnBitmap); } } return returnBitmap; }
/// <summary> /// Make Capture with specified destinations /// </summary> /// <param name="mode">CaptureMode</param> /// <param name="captureMouseCursor">bool false if the mouse should not be captured, true if the configuration should be checked</param> /// <param name="captureDestinations">List<CaptureDestination> with destinations</param> private void MakeCapture(CaptureMode mode, bool captureMouseCursor, ICapture newCapture) { if (screenCapture != null) { screenCapture.Stop(); screenCapture = null; return; } if (captureMode != CaptureMode.None) { LOG.Warn(String.Format("Capture started while capturing, current mode = {0} new capture was {1}.", captureMode, mode)); return; } else { LOG.Debug(String.Format("MakeCapture({0}, {1})", mode, captureMouseCursor)); } captureMode = mode; PrepareForCaptureWithFeedback(mode); // cleanup the previos information if there is still any if (capture != null) { LOG.Debug("Capture wasn't disposed yet, this would suggest a leak"); capture.Dispose(); capture = null; } // Use the supplied Capture information capture = newCapture; if (capture == null) { capture = new Capture(); } capture.CaptureDetails.CaptureMode = mode; // 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(this.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 && mode != CaptureMode.Clipboard && mode != CaptureMode.File) { capture.CursorVisible = conf.CaptureMousepointer; } switch (mode) { case CaptureMode.Window: capture = WindowCapture.CaptureScreen(capture); capture.CaptureDetails.AddMetaData("source", "Screen"); 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"; } // Make sure capturing is stopped at any cost StopCapturing(false); HandleCapture(); break; case CaptureMode.IE: if (IECaptureHelper.CaptureIE(capture) != null) { capture.CaptureDetails.AddMetaData("source", "Internet Explorer"); HandleCapture(); } else { StopCapturing(true); } break; case CaptureMode.FullScreen: 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 capture.CaptureDetails.AddDestination(CaptureDestination.Editor); HandleCapture(); } else { MessageBox.Show("Couldn't create bitmap from : " + text); } break; case CaptureMode.File: Bitmap fileBitmap = null; bool isSaveSupported = true; string filename = capture.CaptureDetails.Filename; if (!string.IsNullOrEmpty(filename)) { try { fileBitmap = ImageHelper.LoadBitmap(filename, ref isSaveSupported); } catch (Exception e) { LOG.Error(e.Message, e); MessageBox.Show(lang.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, this is currently the only usefull destination capture.CaptureDetails.AddDestination(CaptureDestination.Editor); if (!isSaveSupported) { // We can't save icon & wmf, don't supply the filename HandleCapture(); } else { HandleCapture(filename); } } else { // "semi" Fix for Bug #3430555 StopCapturing(true); } break; case CaptureMode.LastRegion: if (!RuntimeConfig.LastCapturedRegion.Equals(Rectangle.Empty)) { capture = WindowCapture.CaptureScreen(capture); capture.Crop(RuntimeConfig.LastCapturedRegion); capture.CaptureDetails.AddMetaData("source", "screen"); HandleCapture(); } else { // Fix for Bug #3430555 StopCapturing(true); } break; case CaptureMode.Region: capture = WindowCapture.CaptureScreen(capture); capture.CaptureDetails.AddMetaData("source", "screen"); CaptureWithFeedback(); 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: " + mode); break; } }
/// <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(); } }
/// <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(); } }