diff --git a/Greenshot/Helpers/CaptureHelper.cs b/Greenshot/Helpers/CaptureHelper.cs index 6b919f0e0..d7f1e8451 100644 --- a/Greenshot/Helpers/CaptureHelper.cs +++ b/Greenshot/Helpers/CaptureHelper.cs @@ -806,7 +806,7 @@ namespace Greenshot.Helpers { windowCaptureMode = WindowCaptureMode.Screen; // Change to GDI, if allowed - if (!windowToCapture.isMetroApp && WindowCapture.isGDIAllowed(process)) { + 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); @@ -817,20 +817,20 @@ namespace Greenshot.Helpers { // Change to DWM, if enabled and allowed if (dwmEnabled) { - if (windowToCapture.isMetroApp || WindowCapture.isDWMAllowed(process)) { + if (windowToCapture.isMetroApp || WindowCapture.IsDwmAllowed(process)) { windowCaptureMode = WindowCaptureMode.Aero; } } } else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) { - if (!dwmEnabled || (!windowToCapture.isMetroApp && !WindowCapture.isDWMAllowed(process))) { + if (!dwmEnabled || (!windowToCapture.isMetroApp && !WindowCapture.IsDwmAllowed(process))) { // Take default screen windowCaptureMode = WindowCaptureMode.Screen; // Change to GDI, if allowed - if (WindowCapture.isGDIAllowed(process)) { + if (WindowCapture.IsGdiAllowed(process)) { windowCaptureMode = WindowCaptureMode.GDI; } } - } else if (windowCaptureMode == WindowCaptureMode.GDI && !WindowCapture.isGDIAllowed(process)) { + } else if (windowCaptureMode == WindowCaptureMode.GDI && !WindowCapture.IsGdiAllowed(process)) { // GDI not allowed, take screen windowCaptureMode = WindowCaptureMode.Screen; } @@ -843,7 +843,7 @@ namespace Greenshot.Helpers { ICapture tmpCapture = null; switch (windowCaptureMode) { case WindowCaptureMode.GDI: - if (WindowCapture.isGDIAllowed(process)) { + if (WindowCapture.IsGdiAllowed(process)) { if (windowToCapture.Iconic) { // Restore the window making sure it's visible! windowToCapture.Restore(); @@ -853,15 +853,15 @@ namespace Greenshot.Helpers { tmpCapture = windowToCapture.CaptureGDIWindow(captureForWindow); if (tmpCapture != null) { // check if GDI capture any good, by comparing it with the screen content - int blackCountGDI = ImageHelper.CountColor((Bitmap)tmpCapture.Image, Color.Black, false); + 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.CaptureRectangle(screenCapture, windowRectangle) != null) { - int blackCountScreen = ImageHelper.CountColor((Bitmap)screenCapture.Image, Color.Black, false); + 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 @@ -901,7 +901,7 @@ namespace Greenshot.Helpers { break; case WindowCaptureMode.Aero: case WindowCaptureMode.AeroTransparent: - if (windowToCapture.isMetroApp || WindowCapture.isDWMAllowed(process)) { + if (windowToCapture.isMetroApp || WindowCapture.IsDwmAllowed(process)) { tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode); } if (tmpCapture != null) { @@ -922,7 +922,7 @@ namespace Greenshot.Helpers { } try { - captureForWindow = WindowCapture.CaptureRectangle(captureForWindow, windowRectangle); + captureForWindow = WindowCapture.CaptureRectangleFromDesktopScreen(captureForWindow, windowRectangle); captureTaken = true; } catch (Exception e) { LOG.Error("Problem capturing", e); diff --git a/GreenshotPlugin/Core/CaptureHandler.cs b/GreenshotPlugin/Core/CaptureHandler.cs new file mode 100644 index 000000000..5ab566c7b --- /dev/null +++ b/GreenshotPlugin/Core/CaptureHandler.cs @@ -0,0 +1,44 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.Drawing; + +namespace GreenshotPlugin.Core { + /// + /// This is the method signature which is used to capture a rectangle from the screen. + /// + /// + /// Captured Bitmap + public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds); + + /// + /// This is a hack to experiment with different screen capture routines + /// + public static class CaptureHandler { + /// + /// By changing this value, null is default + /// + public static CaptureScreenRectangleHandler CaptureScreenRectangle { + get; + set; + } + } +} diff --git a/GreenshotPlugin/Core/ClipboardHelper.cs b/GreenshotPlugin/Core/ClipboardHelper.cs index 56ba02d57..17467fbca 100644 --- a/GreenshotPlugin/Core/ClipboardHelper.cs +++ b/GreenshotPlugin/Core/ClipboardHelper.cs @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/GreenshotPlugin/Core/WindowCapture.cs b/GreenshotPlugin/Core/WindowCapture.cs index 78d9a2dd4..7fcd7f123 100644 --- a/GreenshotPlugin/Core/WindowCapture.cs +++ b/GreenshotPlugin/Core/WindowCapture.cs @@ -37,43 +37,31 @@ namespace GreenshotPlugin.Core { /// The time the Capture was taken and the Title of the window (or a region of) that is captured /// public class CaptureDetails : ICaptureDetails { - private string title; public string Title { - get {return title;} - set {title = value;} + get; + set; } - private string filename; public string Filename { - get {return filename;} - set {filename = value;} + get; + set; } - private DateTime dateTime; public DateTime DateTime { - get {return dateTime;} - set {dateTime = value;} - } - - private float dpiX; - public float DpiX { - get { - return dpiX; - } - set { - dpiX = value; - } + get; + set; } - private float dpiY; - public float DpiY { - get { - return dpiY; - } - set { - dpiY = value; - } + public float DpiX { + get; + set; } + + public float DpiY { + get; + set; + } + private Dictionary metaData = new Dictionary(); public Dictionary MetaData { get {return metaData;} @@ -86,37 +74,36 @@ namespace GreenshotPlugin.Core { metaData.Add(key, value); } } - - private CaptureMode captureMode; + public CaptureMode CaptureMode { - get {return captureMode;} - set {captureMode = value;} + get; + set; } - - private List captureDestinations = new List(); + + private List _captureDestinations = new List(); public List CaptureDestinations { - get {return captureDestinations;} - set {captureDestinations = value;} + get {return _captureDestinations;} + set {_captureDestinations = value;} } public void ClearDestinations() { - captureDestinations.Clear(); + _captureDestinations.Clear(); } public void RemoveDestination(IDestination destination) { - if (captureDestinations.Contains(destination)) { - captureDestinations.Remove(destination); + if (_captureDestinations.Contains(destination)) { + _captureDestinations.Remove(destination); } } public void AddDestination(IDestination captureDestination) { - if (!captureDestinations.Contains(captureDestination)) { - captureDestinations.Add(captureDestination); + if (!_captureDestinations.Contains(captureDestination)) { + _captureDestinations.Add(captureDestination); } } public bool HasDestination(string designation) { - foreach(IDestination destination in captureDestinations) { + foreach(IDestination destination in _captureDestinations) { if (designation.Equals(destination.Designation)) { return true; } @@ -125,7 +112,7 @@ namespace GreenshotPlugin.Core { } public CaptureDetails() { - dateTime = DateTime.Now; + DateTime = DateTime.Now; } } @@ -133,47 +120,47 @@ namespace GreenshotPlugin.Core { /// This class is used to pass an instance of the "Capture" around /// Having the Bitmap, eventually the Windows Title and cursor all together. /// - public class Capture : IDisposable, ICapture { - private static ILog LOG = LogManager.GetLogger(typeof(Capture)); - private List elements = new List(); + public class Capture : ICapture { + private static readonly ILog LOG = LogManager.GetLogger(typeof(Capture)); + private List _elements = new List(); - private Rectangle screenBounds; + private Rectangle _screenBounds = Rectangle.Empty; /// /// Get/Set the Screenbounds /// public Rectangle ScreenBounds { get { - if (screenBounds == null) { - screenBounds = WindowCapture.GetScreenBounds(); + if (_screenBounds == Rectangle.Empty) { + _screenBounds = WindowCapture.GetScreenBounds(); } - return screenBounds; + return _screenBounds; } - set {screenBounds = value;} + set {_screenBounds = value;} } - private Image image; + private Image _image; /// /// Get/Set the Image /// public Image Image { - get {return image;} + get {return _image;} set { - if (image != null) { - image.Dispose(); + if (_image != null) { + _image.Dispose(); } - image = value; + _image = value; if (value != null) { if (value.PixelFormat.Equals(PixelFormat.Format8bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format1bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format4bppIndexed)) { LOG.Debug("Converting Bitmap to PixelFormat.Format32bppArgb as we don't support: " + value.PixelFormat); try { // Default Bitmap PixelFormat is Format32bppArgb - image = new Bitmap(value); + _image = new Bitmap(value); } finally { // Always dispose, even when a exception occured value.Dispose(); } } - LOG.DebugFormat("Image is set with the following specifications: {0} - {1}", image.Size, image.PixelFormat); + LOG.DebugFormat("Image is set with the following specifications: {0} - {1}", _image.Size, _image.PixelFormat); } else { LOG.Debug("Image is removed."); } @@ -181,65 +168,65 @@ namespace GreenshotPlugin.Core { } public void NullImage() { - image = null; + _image = null; } - private Icon cursor; + private Icon _cursor; /// /// Get/Set the image for the Cursor /// public Icon Cursor { - get {return cursor;} + get {return _cursor;} set { - if (cursor != null) { - cursor.Dispose(); + if (_cursor != null) { + _cursor.Dispose(); } - cursor = (Icon)value.Clone(); + _cursor = (Icon)value.Clone(); } } - private bool cursorVisible = false; + private bool _cursorVisible; /// /// Set if the cursor is visible /// public bool CursorVisible { - get {return cursorVisible;} - set {cursorVisible = value;} + get {return _cursorVisible;} + set {_cursorVisible = value;} } - private Point cursorLocation = Point.Empty; + private Point _cursorLocation = Point.Empty; /// /// Get/Set the CursorLocation /// public Point CursorLocation { - get {return cursorLocation;} - set {cursorLocation = value;} + get {return _cursorLocation;} + set {_cursorLocation = value;} } - private Point location = Point.Empty; + private Point _location = Point.Empty; /// /// Get/set the Location /// public Point Location { - get {return location;} - set {location = value;} + get {return _location;} + set {_location = value;} } - private CaptureDetails captureDetails; + private CaptureDetails _captureDetails; /// /// Get/set the CaptureDetails /// public ICaptureDetails CaptureDetails { - get {return captureDetails;} - set {captureDetails = (CaptureDetails)value;} + get {return _captureDetails;} + set {_captureDetails = (CaptureDetails)value;} } /// /// Default Constructor /// public Capture() { - screenBounds = WindowCapture.GetScreenBounds(); - captureDetails = new CaptureDetails(); + _screenBounds = WindowCapture.GetScreenBounds(); + _captureDetails = new CaptureDetails(); } /// @@ -274,15 +261,15 @@ namespace GreenshotPlugin.Core { /// protected virtual void Dispose(bool disposing) { if (disposing) { - if (image != null) { - image.Dispose(); + if (_image != null) { + _image.Dispose(); } - if (cursor != null) { - cursor.Dispose(); + if (_cursor != null) { + _cursor.Dispose(); } } - image = null; - cursor = null; + _image = null; + _cursor = null; } /// @@ -291,8 +278,8 @@ namespace GreenshotPlugin.Core { /// Rectangle with bitmap coordinates public bool Crop(Rectangle cropRectangle) { LOG.Debug("Cropping to: " + cropRectangle.ToString()); - if (ImageHelper.Crop(ref image, ref cropRectangle)) { - location = cropRectangle.Location; + if (ImageHelper.Crop(ref _image, ref cropRectangle)) { + _location = cropRectangle.Location; // Change mouse location according to the cropRegtangle (including screenbounds) offset MoveMouseLocation(-cropRectangle.Location.X, -cropRectangle.Location.Y); // Move all the elements @@ -301,12 +288,12 @@ namespace GreenshotPlugin.Core { // Remove invisible elements List newElements = new List(); - foreach(ICaptureElement captureElement in elements) { + foreach(ICaptureElement captureElement in _elements) { if (captureElement.Bounds.IntersectsWith(cropRectangle)) { newElements.Add(captureElement); } } - elements = newElements; + _elements = newElements; return true; } @@ -320,7 +307,7 @@ namespace GreenshotPlugin.Core { /// x coordinates to move the mouse /// y coordinates to move the mouse public void MoveMouseLocation(int x, int y) { - cursorLocation.Offset(x, y); + _cursorLocation.Offset(x, y); } // TODO: Enable when the elements are usable again. @@ -388,13 +375,13 @@ namespace GreenshotPlugin.Core { Bounds = bounds; } - private List children = new List(); + private List _children = new List(); public List Children { get { - return children; + return _children; } set { - children = value; + _children = value; } } @@ -410,9 +397,9 @@ namespace GreenshotPlugin.Core { // CaptureElements are regarded equal if their bounds are equal. this should be sufficient. public override bool Equals(object obj) { bool ret = false; - if (obj != null && GetType().Equals(obj.GetType())) { + if (obj != null && GetType() == obj.GetType()) { CaptureElement other = obj as CaptureElement; - if (Bounds.Equals(other.Bounds)) { + if (other != null && Bounds.Equals(other.Bounds)) { ret = true; } } @@ -428,7 +415,7 @@ namespace GreenshotPlugin.Core { /// public class WindowCapture { private static readonly ILog LOG = LogManager.GetLogger(typeof(WindowCapture)); - private static CoreConfiguration conf = IniConfig.GetIniSection(); + private static readonly CoreConfiguration Configuration = IniConfig.GetIniSection(); /// /// Used to cleanup the unmanged resource in the iconInfo for the CaptureCursor method @@ -461,8 +448,10 @@ namespace GreenshotPlugin.Core { /// /// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation /// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap. - /// Point with cursor location, relative to the top left corner of the monitor setup (which itself might - /// actually not be on any screen) + /// + /// + /// Point with cursor location, relative to the top left corner of the monitor setup (which itself might actually not be on any screen) + /// public static Point GetCursorLocationRelativeToScreenBounds() { return GetLocationRelativeToScreenBounds(User32.GetCursorLocation()); } @@ -537,7 +526,6 @@ namespace GreenshotPlugin.Core { /// Helper method to create an exception that might explain what is wrong while capturing /// /// string with current method - /// ICapture /// Rectangle of what we want to capture /// private static Exception CreateCaptureException(string method, Rectangle captureBounds) { @@ -554,12 +542,12 @@ namespace GreenshotPlugin.Core { /// /// Process owning the window /// true if it's allowed - public static bool isDWMAllowed(Process process) { + public static bool IsDwmAllowed(Process process) { if (process != null) { - if (conf.NoDWMCaptureForProduct != null && conf.NoDWMCaptureForProduct.Count > 0) { + if (Configuration.NoDWMCaptureForProduct != null && Configuration.NoDWMCaptureForProduct.Count > 0) { try { string productName = process.MainModule.FileVersionInfo.ProductName; - if (productName != null && conf.NoDWMCaptureForProduct.Contains(productName.ToLower())) { + if (productName != null && Configuration.NoDWMCaptureForProduct.Contains(productName.ToLower())) { return false; } } catch (Exception ex) { @@ -573,14 +561,14 @@ namespace GreenshotPlugin.Core { /// /// Helper method to check if it is allowed to capture the process using GDI /// - /// Process owning the window + /// Process owning the window /// true if it's allowed - public static bool isGDIAllowed(Process process) { + public static bool IsGdiAllowed(Process process) { if (process != null) { - if (conf.NoGDICaptureForProduct != null && conf.NoGDICaptureForProduct.Count > 0) { + if (Configuration.NoGDICaptureForProduct != null && Configuration.NoGDICaptureForProduct.Count > 0) { try { string productName = process.MainModule.FileVersionInfo.ProductName; - if (productName != null && conf.NoGDICaptureForProduct.Contains(productName.ToLower())) { + if (productName != null && Configuration.NoGDICaptureForProduct.Contains(productName.ToLower())) { return false; } } catch (Exception ex) { @@ -598,6 +586,25 @@ namespace GreenshotPlugin.Core { /// Rectangle with the bounds to capture /// A Capture Object with a part of the Screen as an Image public static ICapture CaptureRectangle(ICapture capture, Rectangle captureBounds) { + if (capture == null) { + capture = new Capture(); + } + // If the CaptureHandler has a handle use this, otherwise use the CaptureRectangle here + capture.Image = CaptureHandler.CaptureScreenRectangle != null ? CaptureHandler.CaptureScreenRectangle(captureBounds) : CaptureRectangle(captureBounds); + capture.Location = captureBounds.Location; + if (capture.CaptureDetails != null) { + ((Bitmap)capture.Image).SetResolution(capture.CaptureDetails.DpiX, capture.CaptureDetails.DpiY); + } + return capture.Image == null ? null : capture; + } + + /// + /// This method will use User32 code to capture the specified captureBounds from the screen + /// + /// ICapture where the captured Bitmap will be stored + /// Rectangle with the bounds to capture + /// A Capture Object with a part of the Screen as an Image + public static ICapture CaptureRectangleFromDesktopScreen(ICapture capture, Rectangle captureBounds) { if (capture == null) { capture = new Capture(); } @@ -606,10 +613,7 @@ namespace GreenshotPlugin.Core { if (capture.CaptureDetails != null) { ((Bitmap)capture.Image).SetResolution(capture.CaptureDetails.DpiX, capture.CaptureDetails.DpiY); } - if (capture.Image == null) { - return null; - } - return capture; + return capture.Image == null ? null : capture; } /// @@ -622,9 +626,9 @@ namespace GreenshotPlugin.Core { if (captureBounds.Height <= 0 || captureBounds.Width <= 0) { LOG.Warn("Nothing to capture, ignoring!"); return null; - } else { - LOG.Debug("CaptureRectangle Called!"); } + LOG.Debug("CaptureRectangle Called!"); + // .NET GDI+ Solution, according to some post this has a GDI+ leak... // See http://connect.microsoft.com/VisualStudio/feedback/details/344752/gdi-object-leak-when-calling-graphics-copyfromscreen // Bitmap capturedBitmap = new Bitmap(captureBounds.Width, captureBounds.Height); @@ -668,69 +672,70 @@ namespace GreenshotPlugin.Core { // Throw so people can report the problem throw exceptionToThrow; - } else { - // select the bitmap object and store the old handle - using (SafeSelectObjectHandle selectObject = safeCompatibleDCHandle.SelectObject(safeDibSectionHandle)) { - // bitblt over (make copy) - GDI32.BitBlt(safeCompatibleDCHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDCHandle, captureBounds.X, captureBounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt); - } + } + // select the bitmap object and store the old handle + using (safeCompatibleDCHandle.SelectObject(safeDibSectionHandle)) { + // bitblt over (make copy) + GDI32.BitBlt(safeCompatibleDCHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDCHandle, captureBounds.X, captureBounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt); + } - // get a .NET image object for it - // A suggestion for the "A generic error occurred in GDI+." E_FAIL/0×80004005 error is to re-try... - bool success = false; - ExternalException exception = null; - for (int i = 0; i < 3; i++) { - try { - // Collect all screens inside this capture - List screensInsideCapture = new List(); - foreach (Screen screen in Screen.AllScreens) { - if (screen.Bounds.IntersectsWith(captureBounds)) { - screensInsideCapture.Add(screen); - } + // get a .NET image object for it + // A suggestion for the "A generic error occurred in GDI+." E_FAIL/0×80004005 error is to re-try... + bool success = false; + ExternalException exception = null; + for (int i = 0; i < 3; i++) { + try { + // Collect all screens inside this capture + List screensInsideCapture = new List(); + foreach (Screen screen in Screen.AllScreens) { + if (screen.Bounds.IntersectsWith(captureBounds)) { + screensInsideCapture.Add(screen); } - // Check all all screens are of an equal size - bool offscreenContent = false; - using (Region captureRegion = new Region(captureBounds)) { - // Exclude every visible part - foreach (Screen screen in screensInsideCapture) { - captureRegion.Exclude(screen.Bounds); - } - // If the region is not empty, we have "offscreenContent" - using (Graphics screenGraphics = Graphics.FromHwnd(User32.GetDesktopWindow())) { - offscreenContent = !captureRegion.IsEmpty(screenGraphics); - } + } + // Check all all screens are of an equal size + bool offscreenContent; + using (Region captureRegion = new Region(captureBounds)) { + // Exclude every visible part + foreach (Screen screen in screensInsideCapture) { + captureRegion.Exclude(screen.Bounds); } - // Check if we need to have a transparent background, needed for offscreen content - if (offscreenContent) { - using (Bitmap tmpBitmap = Bitmap.FromHbitmap(safeDibSectionHandle.DangerousGetHandle())) { - // Create a new bitmap which has a transparent background - returnBitmap = ImageHelper.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution); - // Content will be copied here - using (Graphics graphics = Graphics.FromImage(returnBitmap)) { - // For all screens copy the content to the new bitmap - foreach (Screen screen in Screen.AllScreens) { - Rectangle screenBounds = screen.Bounds; - // Make sure the bounds are offsetted to the capture bounds - screenBounds.Offset(-captureBounds.X, -captureBounds.Y); - graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel); - } + // If the region is not empty, we have "offscreenContent" + using (Graphics screenGraphics = Graphics.FromHwnd(User32.GetDesktopWindow())) { + offscreenContent = !captureRegion.IsEmpty(screenGraphics); + } + } + // Check if we need to have a transparent background, needed for offscreen content + if (offscreenContent) { + using (Bitmap tmpBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle())) { + // Create a new bitmap which has a transparent background + returnBitmap = ImageHelper.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution); + // Content will be copied here + using (Graphics graphics = Graphics.FromImage(returnBitmap)) { + // For all screens copy the content to the new bitmap + foreach (Screen screen in Screen.AllScreens) { + Rectangle screenBounds = screen.Bounds; + // Make sure the bounds are offsetted to the capture bounds + screenBounds.Offset(-captureBounds.X, -captureBounds.Y); + graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel); } } - } else { - // All screens, which are inside the capture, are of equal size - // assign image to Capture, the image will be disposed there.. - returnBitmap = Bitmap.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()); } - // We got through the capture without exception - success = true; - break; - } catch (ExternalException ee) { - LOG.Warn("Problem getting bitmap at try " + i + " : ", ee); - exception = ee; + } else { + // All screens, which are inside the capture, are of equal size + // assign image to Capture, the image will be disposed there.. + returnBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()); } + // We got through the capture without exception + success = true; + break; + } catch (ExternalException ee) { + LOG.Warn("Problem getting bitmap at try " + i + " : ", ee); + exception = ee; } - if (!success) { - LOG.Error("Still couldn't create Bitmap!"); + } + if (!success) { + LOG.Error("Still couldn't create Bitmap!"); + if (exception != null) { throw exception; } } diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs index 0998ef253..6be142762 100644 --- a/GreenshotPlugin/Core/WindowsHelper.cs +++ b/GreenshotPlugin/Core/WindowsHelper.cs @@ -18,31 +18,29 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Windows.Forms; + using Greenshot.IniFile; using Greenshot.Interop; using Greenshot.Plugin; using GreenshotPlugin.UnmanagedHelpers; +using log4net; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; + /// /// Code for handling with "windows" /// Main code is taken from vbAccelerator, location: /// http://www.vbaccelerator.com/home/NET/Code/Libraries/Windows/Enumerating_Windows/article.asp /// but a LOT of changes/enhancements were made to adapt it for Greenshot. /// -using log4net; - -namespace GreenshotPlugin.Core { +namespace GreenshotPlugin.Core { #region EnumWindows /// /// EnumWindows wrapper for .NET @@ -73,7 +71,7 @@ namespace GreenshotPlugin.Core { /// /// Gets all child windows of the specified window /// - /// Window Handle to get children for + /// Window Handle to get children for public WindowsEnumerator GetWindows(WindowDetails parent) { if (parent != null) { GetWindows(parent.Handle, null); @@ -167,7 +165,6 @@ namespace GreenshotPlugin.Core { private const string METRO_GUTTER_CLASS = "ImmersiveGutter"; private static ILog LOG = LogManager.GetLogger(typeof(WindowDetails)); - private static Dictionary> classnameTree = new Dictionary>(); private static CoreConfiguration conf = IniConfig.GetIniSection(); private static List ignoreHandles = new List(); private static List excludeProcessesFromFreeze = new List(); @@ -988,7 +985,7 @@ namespace GreenshotPlugin.Core { if (!doesCaptureFit) { // if GDI is allowed.. (a screenshot won't be better than we comes if we continue) using (Process thisWindowProcess = Process) { - if (!isMetroApp && WindowCapture.isGDIAllowed(thisWindowProcess)) { + if (!isMetroApp && WindowCapture.IsGdiAllowed(thisWindowProcess)) { // we return null which causes the capturing code to try another method. return null; } diff --git a/GreenshotPlugin/GreenshotPlugin.csproj b/GreenshotPlugin/GreenshotPlugin.csproj index b7fd9549c..eb956765e 100644 --- a/GreenshotPlugin/GreenshotPlugin.csproj +++ b/GreenshotPlugin/GreenshotPlugin.csproj @@ -34,6 +34,7 @@ Component +