diff --git a/Greenshot/Forms/MainForm.cs b/Greenshot/Forms/MainForm.cs index 686f507d4..19643627a 100644 --- a/Greenshot/Forms/MainForm.cs +++ b/Greenshot/Forms/MainForm.cs @@ -908,7 +908,7 @@ namespace Greenshot { public void AddCaptureWindowMenuItems(ToolStripMenuItem menuItem, EventHandler eventHandler) { menuItem.DropDownItems.Clear(); // check if thumbnailPreview is enabled and DWM is enabled - bool thumbnailPreview = _conf.ThumnailPreview && DWM.isDWMEnabled(); + bool thumbnailPreview = _conf.ThumnailPreview && DWM.IsDwmEnabled(); List windows = WindowDetails.GetTopLevelWindows(); foreach(WindowDetails window in windows) { diff --git a/Greenshot/Forms/SettingsForm.cs b/Greenshot/Forms/SettingsForm.cs index 10b8cec7a..59f8c85be 100644 --- a/Greenshot/Forms/SettingsForm.cs +++ b/Greenshot/Forms/SettingsForm.cs @@ -146,7 +146,7 @@ namespace Greenshot { private void SetWindowCaptureMode(WindowCaptureMode selectedWindowCaptureMode) { WindowCaptureMode[] availableModes; - if (!DWM.isDWMEnabled()) { + if (!DWM.IsDwmEnabled()) { // Remove DWM from configuration, as DWM is disabled! if (coreConfiguration.WindowCaptureMode == WindowCaptureMode.Aero || coreConfiguration.WindowCaptureMode == WindowCaptureMode.AeroTransparent) { coreConfiguration.WindowCaptureMode = WindowCaptureMode.GDI; diff --git a/Greenshot/Helpers/CaptureHelper.cs b/Greenshot/Helpers/CaptureHelper.cs index 5d3868194..fa12e5e30 100644 --- a/Greenshot/Helpers/CaptureHelper.cs +++ b/Greenshot/Helpers/CaptureHelper.cs @@ -693,7 +693,10 @@ namespace Greenshot.Helpers { } else { _selectedCaptureWindow = WindowDetails.GetActiveWindow(); if (_selectedCaptureWindow != null) { - LOG.DebugFormat("Capturing window: {0} with {1}", _selectedCaptureWindow.Text, _selectedCaptureWindow.WindowRectangle); + if (LOG.IsDebugEnabled) + { + LOG.DebugFormat("Capturing window: {0} with {1}", _selectedCaptureWindow.Text, _selectedCaptureWindow.WindowRectangle); + } } } if (_selectedCaptureWindow == null || (!presupplied && _selectedCaptureWindow.Iconic)) { @@ -731,7 +734,6 @@ namespace Greenshot.Helpers { // Trying workaround, the size 0 arrises with e.g. Toad.exe, has a different Window when minimized WindowDetails linkedWindow = WindowDetails.GetLinkedWindow(windowToCapture); if (linkedWindow != null) { - windowRectangle = linkedWindow.WindowRectangle; windowToCapture = linkedWindow; } else { return null; @@ -777,7 +779,7 @@ namespace Greenshot.Helpers { Rectangle windowRectangle = windowToCapture.WindowRectangle; // When Vista & DWM (Aero) enabled - bool dwmEnabled = DWM.isDWMEnabled(); + bool dwmEnabled = DWM.IsDwmEnabled(); // get process name to be able to exclude certain processes from certain capture modes using (Process process = windowToCapture.Process) { bool isAutoMode = windowCaptureMode == WindowCaptureMode.Auto; @@ -801,7 +803,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); @@ -812,12 +814,12 @@ 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 @@ -845,32 +847,32 @@ namespace Greenshot.Helpers { } else { windowToCapture.ToForeground(); } - tmpCapture = windowToCapture.CaptureGDIWindow(captureForWindow); + tmpCapture = windowToCapture.CaptureGdiWindow(captureForWindow); if (tmpCapture != null) { // check if GDI capture any good, by comparing it with the screen content - int blackCountGDI = ImageHelper.CountColor(tmpCapture.Image, Color.Black, false); - int GDIPixels = tmpCapture.Image.Width * tmpCapture.Image.Height; - int blackPercentageGDI = blackCountGDI * 100 / GDIPixels; - if (blackPercentageGDI >= 1) { + int blackCountGdi = ImageHelper.CountColor(tmpCapture.Image, Color.Black, false); + int gdiPixels = tmpCapture.Image.Width * tmpCapture.Image.Height; + int blackPercentageGdi = blackCountGdi * 100 / gdiPixels; + if (blackPercentageGdi >= 1) { int screenPixels = windowRectangle.Width * windowRectangle.Height; using (ICapture screenCapture = new Capture()) { screenCapture.CaptureDetails = captureForWindow.CaptureDetails; if (WindowCapture.CaptureRectangleFromDesktopScreen(screenCapture, windowRectangle) != null) { int blackCountScreen = ImageHelper.CountColor(screenCapture.Image, Color.Black, false); int blackPercentageScreen = blackCountScreen * 100 / screenPixels; - if (screenPixels == GDIPixels) { + if (screenPixels == gdiPixels) { // "easy compare", both have the same size // If GDI has more black, use the screen capture. - if (blackPercentageGDI > blackPercentageScreen) { + if (blackPercentageGdi > blackPercentageScreen) { LOG.Debug("Using screen capture, as GDI had additional black."); // changeing the image will automatically dispose the previous tmpCapture.Image = screenCapture.Image; // Make sure it's not disposed, else the picture is gone! screenCapture.NullImage(); } - } else if (screenPixels < GDIPixels) { + } else if (screenPixels < gdiPixels) { // Screen capture is cropped, window is outside of screen - if (blackPercentageGDI > 50 && blackPercentageGDI > blackPercentageScreen) { + if (blackPercentageGdi > 50 && blackPercentageGdi > blackPercentageScreen) { LOG.Debug("Using screen capture, as GDI had additional black."); // changeing the image will automatically dispose the previous tmpCapture.Image = screenCapture.Image; @@ -896,8 +898,8 @@ namespace Greenshot.Helpers { break; case WindowCaptureMode.Aero: case WindowCaptureMode.AeroTransparent: - if (windowToCapture.isMetroApp || WindowCapture.IsDwmAllowed(process)) { - tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode); + if (windowToCapture.IsMetroApp || WindowCapture.IsDwmAllowed(process)) { + tmpCapture = windowToCapture.CaptureDwmWindow(captureForWindow, windowCaptureMode, isAutoMode); } if (tmpCapture != null) { captureForWindow = tmpCapture; diff --git a/Greenshot/releases/additional_files/readme.txt.template b/Greenshot/releases/additional_files/readme.txt.template index 3668769d5..f836f567f 100644 --- a/Greenshot/releases/additional_files/readme.txt.template +++ b/Greenshot/releases/additional_files/readme.txt.template @@ -35,6 +35,7 @@ This version has changes, compared to 1.2.8.12, for the following reported ticke * BUG-1941: Error when creating speech bubble| * BUG-1945: Failure starting Greenshot at system startup| * BUG-1949: Can't delete Imgur upload +* BUG-1965: Activation border around window is visible in the capture * FEATURE-945: Added environment variables to the external command Testing is not finished, use at your own risk... diff --git a/GreenshotPlugin/Controls/ThumbnailForm.cs b/GreenshotPlugin/Controls/ThumbnailForm.cs index 121798e00..4155eef9f 100644 --- a/GreenshotPlugin/Controls/ThumbnailForm.cs +++ b/GreenshotPlugin/Controls/ThumbnailForm.cs @@ -77,10 +77,10 @@ namespace GreenshotPlugin.Controls { SIZE sourceSize; DWM.DwmQueryThumbnailSourceSize(_thumbnailHandle, out sourceSize); int thumbnailHeight = 200; - int thumbnailWidth = (int)(thumbnailHeight * ((float)sourceSize.width / (float)sourceSize.height)); + int thumbnailWidth = (int)(thumbnailHeight * ((float)sourceSize.Width / (float)sourceSize.Height)); if (parentControl != null && thumbnailWidth > parentControl.Width) { thumbnailWidth = parentControl.Width; - thumbnailHeight = (int)(thumbnailWidth * ((float)sourceSize.height / (float)sourceSize.width)); + thumbnailHeight = (int)(thumbnailWidth * ((float)sourceSize.Height / (float)sourceSize.Width)); } Width = thumbnailWidth; Height = thumbnailHeight; diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs index 0fa642128..08259c1bd 100644 --- a/GreenshotPlugin/Core/WindowsHelper.cs +++ b/GreenshotPlugin/Core/WindowsHelper.cs @@ -26,6 +26,7 @@ using GreenshotPlugin.UnmanagedHelpers; using log4net; using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; @@ -34,12 +35,6 @@ 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. -/// namespace GreenshotPlugin.Core { #region EnumWindows /// @@ -139,7 +134,7 @@ namespace GreenshotPlugin.Core { /// Window handle to add /// True to continue enumeration, False to stop protected virtual bool OnWindowEnum(IntPtr hWnd) { - if (!WindowDetails.isIgnoreHandle(hWnd)) { + if (!WindowDetails.IsIgnoreHandle(hWnd)) { items.Add(new WindowDetails(hWnd)); } return true; @@ -150,12 +145,16 @@ namespace GreenshotPlugin.Core { // nothing to do } #endregion - } + } #endregion EnumWindows - /// #region WindowDetails /// + /// 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. + /// /// Provides details about a Window returned by the /// enumeration /// @@ -165,9 +164,9 @@ namespace GreenshotPlugin.Core { private const string METRO_GUTTER_CLASS = "ImmersiveGutter"; private static readonly ILog LOG = LogManager.GetLogger(typeof(WindowDetails)); - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - private static readonly List ignoreHandles = new List(); - private static readonly List excludeProcessesFromFreeze = new List(); + private static readonly CoreConfiguration Conf = IniConfig.GetIniSection(); + private static readonly List IgnoreHandles = new List(); + private static readonly List ExcludeProcessesFromFreeze = new List(); private static readonly IAppVisibility appVisibility; static WindowDetails() { @@ -180,33 +179,33 @@ namespace GreenshotPlugin.Core { } public static void AddProcessToExcludeFromFreeze(string processname) { - if (!excludeProcessesFromFreeze.Contains(processname)) { - excludeProcessesFromFreeze.Add(processname); + if (!ExcludeProcessesFromFreeze.Contains(processname)) { + ExcludeProcessesFromFreeze.Add(processname); } } - internal static bool isIgnoreHandle(IntPtr handle) { - return ignoreHandles.Contains(handle); + internal static bool IsIgnoreHandle(IntPtr handle) { + return IgnoreHandles.Contains(handle); } - private List childWindows; - private IntPtr parentHandle = IntPtr.Zero; - private WindowDetails parent; - private bool frozen; + private List _childWindows; + private IntPtr _parentHandle = IntPtr.Zero; + private WindowDetails _parent; + private bool _frozen; - public bool isApp { + public bool IsApp { get { return METRO_WINDOWS_CLASS.Equals(ClassName); } } - public bool isGutter { + public bool IsGutter { get { return METRO_GUTTER_CLASS.Equals(ClassName); } } - public bool isAppLauncher { + public bool IsAppLauncher { get { return METRO_APPLAUNCHER_CLASS.Equals(ClassName); } @@ -215,16 +214,16 @@ namespace GreenshotPlugin.Core { /// /// Check if this window is the window of a metro app /// - public bool isMetroApp { + public bool IsMetroApp { get { - return isAppLauncher || isApp; + return IsAppLauncher || IsApp; } } /// /// The window handle. /// - private readonly IntPtr hWnd = IntPtr.Zero; + private readonly IntPtr _hWnd = IntPtr.Zero; /// /// To allow items to be compared, the hash code @@ -257,15 +256,15 @@ namespace GreenshotPlugin.Core { public bool HasChildren { get { - return (childWindows != null) && (childWindows.Count > 0); + return (_childWindows != null) && (_childWindows.Count > 0); } } public void FreezeDetails() { - frozen = true; + _frozen = true; } public void UnfreezeDetails() { - frozen = false; + _frozen = false; } public string ProcessPath { @@ -297,7 +296,7 @@ namespace GreenshotPlugin.Core { LOG.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message); LOG.Warn(ex); } - if (isMetroApp) { + if (IsMetroApp) { // No method yet to get the metro icon return null; } @@ -321,8 +320,8 @@ namespace GreenshotPlugin.Core { IntPtr ICON_BIG = new IntPtr(1); IntPtr ICON_SMALL2 = new IntPtr(2); - IntPtr iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, IntPtr.Zero); - if (conf.UseLargeIcons) { + IntPtr iconHandle; + if (Conf.UseLargeIcons) { iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, IntPtr.Zero); if (iconHandle == IntPtr.Zero) { iconHandle = User32.GetClassLongWrapper(hwnd, (int)ClassLongIndex.GCL_HICON); @@ -357,7 +356,7 @@ namespace GreenshotPlugin.Core { /// /// public static void RegisterIgnoreHandle(IntPtr ignoreHandle) { - ignoreHandles.Add(ignoreHandle); + IgnoreHandles.Add(ignoreHandle); } /// @@ -365,24 +364,25 @@ namespace GreenshotPlugin.Core { /// /// public static void UnregisterIgnoreHandle(IntPtr ignoreHandle) { - ignoreHandles.Remove(ignoreHandle); + IgnoreHandles.Remove(ignoreHandle); } public List Children { get { - if (childWindows == null) { + if (_childWindows == null) { GetChildren(); } - return childWindows; + return _childWindows; } } /// /// Retrieve all windows with a certain title or classname /// + /// /// The regexp to look for in the title /// The regexp to look for in the classname - /// List with all the found windows + /// List WindowDetails with all the found windows private static List FindWindow(List windows, string titlePattern, string classnamePattern) { List foundWindows = new List(); Regex titleRegexp = null; @@ -430,16 +430,16 @@ namespace GreenshotPlugin.Core { public IntPtr ParentHandle { get { - if (parentHandle == IntPtr.Zero) { - parentHandle = User32.GetParent(Handle); - parent = null; + if (_parentHandle == IntPtr.Zero) { + _parentHandle = User32.GetParent(Handle); + _parent = null; } - return parentHandle; + return _parentHandle; } set { - if (parentHandle != value) { - parentHandle = value; - parent = null; + if (_parentHandle != value) { + _parentHandle = value; + _parent = null; } } } @@ -448,15 +448,15 @@ namespace GreenshotPlugin.Core { /// /// WindowDetails of the parent, or null if none public WindowDetails GetParent() { - if (parent == null) { - if (parentHandle == IntPtr.Zero) { - parentHandle = User32.GetParent(Handle); + if (_parent == null) { + if (_parentHandle == IntPtr.Zero) { + _parentHandle = User32.GetParent(Handle); } - if (parentHandle != IntPtr.Zero) { - parent = new WindowDetails(parentHandle); + if (_parentHandle != IntPtr.Zero) { + _parent = new WindowDetails(_parentHandle); } } - return parent; + return _parent; } /// @@ -464,10 +464,10 @@ namespace GreenshotPlugin.Core { /// One should normally use the getter "Children" /// public List GetChildren() { - if (childWindows == null) { + if (_childWindows == null) { return GetChildren(0); } - return childWindows; + return _childWindows; } /// @@ -475,16 +475,16 @@ namespace GreenshotPlugin.Core { /// /// Specify how many levels we go in public List GetChildren(int levelsToGo) { - if (childWindows == null) { - childWindows = new List(); - foreach(WindowDetails childWindow in new WindowsEnumerator().GetWindows(hWnd, null).Items) { - childWindows.Add(childWindow); + if (_childWindows == null) { + _childWindows = new List(); + foreach(WindowDetails childWindow in new WindowsEnumerator().GetWindows(_hWnd, null).Items) { + _childWindows.Add(childWindow); if (levelsToGo > 0) { childWindow.GetChildren(levelsToGo-1); } } } - return childWindows; + return _childWindows; } /// @@ -492,7 +492,7 @@ namespace GreenshotPlugin.Core { /// /// The regexp to look for in the title /// The regexp to look for in the classname - /// List with all the found windows, or an empty list + /// List WindowDetails with all the found windows, or an empty list public List FindChildren(string titlePattern, string classnamePattern) { return FindWindow(Children, titlePattern, classnamePattern); } @@ -500,7 +500,7 @@ namespace GreenshotPlugin.Core { /// /// Recursing helper method for the FindPath /// - /// List with classnames + /// List string with classnames /// The index in the list to look for /// WindowDetails if a match was found private WindowDetails FindPath(List classnames, int index) { @@ -542,6 +542,7 @@ namespace GreenshotPlugin.Core { /// /// Deep scan for a certain classname pattern /// + /// Window to scan into /// Classname regexp pattern /// The first WindowDetails found public static WindowDetails DeepScan(WindowDetails windowDetails, Regex classnamePattern) { @@ -575,7 +576,7 @@ namespace GreenshotPlugin.Core { return null; } WindowDetails windowDetails = new WindowDetails(tmphWnd); - windowDetails.parent = this; + windowDetails._parent = this; return windowDetails; } @@ -584,38 +585,38 @@ namespace GreenshotPlugin.Core { /// public IntPtr Handle { get { - return hWnd; + return _hWnd; } } - private string text; + private string _text; /// /// Gets the window's title (caption) /// public string Text { set { - text = value; + _text = value; } get { - if (text == null) { + if (_text == null) { StringBuilder title = new StringBuilder(260, 260); - User32.GetWindowText(hWnd, title, title.Capacity); - text = title.ToString(); + User32.GetWindowText(_hWnd, title, title.Capacity); + _text = title.ToString(); } - return text; + return _text; } } - private string className; + private string _className; /// /// Gets the window's class name. /// public string ClassName { get { - if (className == null) { - className = GetClassName(hWnd); + if (_className == null) { + _className = GetClassName(_hWnd); } - return className; + return _className; } } @@ -624,16 +625,16 @@ namespace GreenshotPlugin.Core { /// public bool Iconic { get { - if (isMetroApp) { + if (IsMetroApp) { return !Visible; } - return User32.IsIconic(hWnd) || Location.X <= -32000; + return User32.IsIconic(_hWnd) || Location.X <= -32000; } set { if (value) { - User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero); + User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero); } else { - User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero); + User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero); } } } @@ -643,7 +644,7 @@ namespace GreenshotPlugin.Core { /// public bool Maximised { get { - if (isApp) { + if (IsApp) { if (Visible) { Rectangle windowRectangle = WindowRectangle; foreach (Screen screen in Screen.AllScreens) { @@ -656,13 +657,13 @@ namespace GreenshotPlugin.Core { } return false; } - return User32.IsZoomed(hWnd); + return User32.IsZoomed(_hWnd); } set { if (value) { - User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MAXIMIZE, IntPtr.Zero); + User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MAXIMIZE, IntPtr.Zero); } else { - User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero); + User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero); } } } @@ -679,7 +680,7 @@ namespace GreenshotPlugin.Core { /// public bool Visible { get { - if (isApp) { + if (IsApp) { Rectangle windowRectangle = WindowRectangle; foreach (Screen screen in Screen.AllScreens) { if (screen.Bounds.Contains(windowRectangle)) { @@ -705,21 +706,21 @@ namespace GreenshotPlugin.Core { } return false; } - if (isGutter) { + if (IsGutter) { // gutter is only made available when it's visible return true; } - if (isAppLauncher) { + if (IsAppLauncher) { return IsAppLauncherVisible; } - return User32.IsWindowVisible(hWnd); + return User32.IsWindowVisible(_hWnd); } } public bool HasParent { get { GetParent(); - return parentHandle != IntPtr.Zero; + return _parentHandle != IntPtr.Zero; } } @@ -751,12 +752,12 @@ namespace GreenshotPlugin.Core { /// Make sure the next call of a cached value is guaranteed the real value /// public void Reset() { - previousWindowRectangle = Rectangle.Empty; + _previousWindowRectangle = Rectangle.Empty; } - private Rectangle previousWindowRectangle = Rectangle.Empty; - private long lastWindowRectangleRetrieveTime; - private const long CACHE_TIME = TimeSpan.TicksPerSecond * 2; + private Rectangle _previousWindowRectangle = Rectangle.Empty; + private long _lastWindowRectangleRetrieveTime; + private const long CacheTime = TimeSpan.TicksPerSecond * 2; /// /// Gets the bounding rectangle of the window /// @@ -764,39 +765,48 @@ namespace GreenshotPlugin.Core { get { // Try to return a cached value long now = DateTime.Now.Ticks; - if (previousWindowRectangle.IsEmpty || !frozen) { - if (previousWindowRectangle.IsEmpty || now - lastWindowRectangleRetrieveTime > CACHE_TIME) { + if (_previousWindowRectangle.IsEmpty || !_frozen) { + if (_previousWindowRectangle.IsEmpty || now - _lastWindowRectangleRetrieveTime > CacheTime) { Rectangle windowRect = Rectangle.Empty; - if (DWM.isDWMEnabled()) { + if (DWM.IsDwmEnabled() && !Maximised) { if (GetExtendedFrameBounds(out windowRect) && Environment.OSVersion.IsWindows10()) { - lastWindowRectangleRetrieveTime = now; - previousWindowRectangle = windowRect; - // DWM does it corectly, just return the window rectangle we just gotten. + _lastWindowRectangleRetrieveTime = now; + // Somehow DWM doesn't calculate it corectly, there is a 1 pixel border around the capture + // Remove this border, currently it's fixed but TODO: Make it depend on the OS? + windowRect.Inflate(-1, -1); + _previousWindowRectangle = windowRect; return windowRect; } } if (windowRect.IsEmpty) { - GetWindowRect(out windowRect); + if (GetWindowRect(out windowRect)) + { + Win32Error error = Win32.GetLastErrorCode(); + LOG.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error)); + } } // Correction for maximized windows, only if it's not an app - if (!HasParent && !isApp && Maximised) { - Size size = Size.Empty; - GetBorderSize(out size); - windowRect = new Rectangle(windowRect.X + size.Width, windowRect.Y + size.Height, windowRect.Width - (2 * size.Width), windowRect.Height - (2 * size.Height)); + if (!HasParent && !IsApp && Maximised) { + Size size; + // Only if the border size can be retrieved + if (GetBorderSize(out size)) + { + windowRect = new Rectangle(windowRect.X + size.Width, windowRect.Y + size.Height, windowRect.Width - (2 * size.Width), windowRect.Height - (2 * size.Height)); + } } - lastWindowRectangleRetrieveTime = now; + _lastWindowRectangleRetrieveTime = now; // Try to return something valid, by getting returning the previous size if the window doesn't have a Rectangle anymore if (windowRect.IsEmpty) { - return previousWindowRectangle; + return _previousWindowRectangle; } - previousWindowRectangle = windowRect; + _previousWindowRectangle = windowRect; return windowRect; } } - return previousWindowRectangle; + return _previousWindowRectangle; } } @@ -825,8 +835,12 @@ namespace GreenshotPlugin.Core { /// public Rectangle ClientRectangle { get { - Rectangle clientRect = Rectangle.Empty; - GetClientRect(out clientRect); + Rectangle clientRect; + if (GetClientRect(out clientRect)) + { + Win32Error error = Win32.GetLastErrorCode(); + LOG.WarnFormat("Couldn't retrieve the client rectangle: {0}", Win32.GetMessage(error)); + } return clientRect; } } @@ -846,10 +860,10 @@ namespace GreenshotPlugin.Core { /// public void Restore() { if (Iconic) { - User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero); + User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero); } - User32.BringWindowToTop(hWnd); - User32.SetForegroundWindow(hWnd); + User32.BringWindowToTop(_hWnd); + User32.SetForegroundWindow(_hWnd); // Make sure windows has time to perform the action while(Iconic) { Application.DoEvents(); @@ -861,10 +875,10 @@ namespace GreenshotPlugin.Core { /// public WindowStyleFlags WindowStyle { get { - return (WindowStyleFlags)User32.GetWindowLongWrapper(hWnd, (int)WindowLongIndex.GWL_STYLE); + return (WindowStyleFlags)User32.GetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_STYLE); } set { - User32.SetWindowLongWrapper(hWnd, (int)WindowLongIndex.GWL_STYLE, new IntPtr((long)value)); + User32.SetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_STYLE, new IntPtr((long)value)); } } @@ -887,10 +901,10 @@ namespace GreenshotPlugin.Core { /// public ExtendedWindowStyleFlags ExtendedWindowStyle { get { - return (ExtendedWindowStyleFlags)User32.GetWindowLongWrapper(hWnd, (int)WindowLongIndex.GWL_EXSTYLE); + return (ExtendedWindowStyleFlags)User32.GetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_EXSTYLE); } set { - User32.SetWindowLongWrapper(hWnd, (int)WindowLongIndex.GWL_EXSTYLE, new IntPtr((uint)value)); + User32.SetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_EXSTYLE, new IntPtr((uint)value)); } } @@ -899,7 +913,7 @@ namespace GreenshotPlugin.Core { /// /// The capture to fill /// ICapture - public ICapture CaptureGDIWindow(ICapture capture) { + public ICapture CaptureGdiWindow(ICapture capture) { Image capturedImage = PrintWindow(); if (capturedImage != null) { capture.Image = capturedImage; @@ -916,7 +930,7 @@ namespace GreenshotPlugin.Core { /// Wanted WindowCaptureMode /// True if auto modus is used /// ICapture with the capture - public ICapture CaptureDWMWindow(ICapture capture, WindowCaptureMode windowCaptureMode, bool autoMode) { + public ICapture CaptureDwmWindow(ICapture capture, WindowCaptureMode windowCaptureMode, bool autoMode) { IntPtr thumbnailHandle = IntPtr.Zero; Form tempForm = null; bool tempFormShown = false; @@ -935,13 +949,13 @@ namespace GreenshotPlugin.Core { SIZE sourceSize; DWM.DwmQueryThumbnailSourceSize(thumbnailHandle, out sourceSize); - if (sourceSize.width <= 0 || sourceSize.height <= 0) { + if (sourceSize.Width <= 0 || sourceSize.Height <= 0) { return null; } // Calculate the location of the temp form Rectangle windowRectangle = WindowRectangle; - Point formLocation = formLocation = windowRectangle.Location; + Point formLocation = windowRectangle.Location; Size borderSize = new Size(); bool doesCaptureFit = false; if (!Maximised) { @@ -950,7 +964,7 @@ namespace GreenshotPlugin.Core { using (Region workingArea = new Region(Screen.PrimaryScreen.Bounds)) { // Find the screen where the window is and check if it fits foreach (Screen screen in Screen.AllScreens) { - if (screen != Screen.PrimaryScreen) { + if (!Equals(screen, Screen.PrimaryScreen)) { workingArea.Union(screen.Bounds); } } @@ -980,32 +994,34 @@ namespace GreenshotPlugin.Core { tempForm.Size = sourceSize.ToSize(); // Prepare rectangle to capture from the screen. - Rectangle captureRectangle = new Rectangle(formLocation.X, formLocation.Y, sourceSize.width, sourceSize.height); + Rectangle captureRectangle = new Rectangle(formLocation.X, formLocation.Y, sourceSize.Width, sourceSize.Height); if (Maximised) { // Correct capture size for maximized window by offsetting the X,Y with the border size - captureRectangle.X += borderSize.Width; - captureRectangle.Y += borderSize.Height; // and subtracting the border from the size (2 times, as we move right/down for the capture without resizing) - captureRectangle.Width -= 2 * borderSize.Width; - captureRectangle.Height -= 2 * borderSize.Height; - } else if (autoMode) { - // check if the capture fits - 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)) { - // we return null which causes the capturing code to try another method. - return null; + captureRectangle.Inflate(borderSize.Width, borderSize.Height); + } else { + captureRectangle.Inflate(-1, -1); + + if (autoMode) { + // check if the capture fits + 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)) { + // we return null which causes the capturing code to try another method. + return null; + } } } } } - // Prepare the displaying of the Thumbnail - DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES(); - props.Opacity = (byte)255; - props.Visible = true; - props.Destination = new RECT(0, 0, sourceSize.width, sourceSize.height); + DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES + { + Opacity = 255, + Visible = true, + Destination = new RECT(0, 0, sourceSize.Width, sourceSize.Height) + }; DWM.DwmUpdateThumbnailProperties(thumbnailHandle, ref props); tempForm.Show(); tempFormShown = true; @@ -1032,7 +1048,7 @@ namespace GreenshotPlugin.Core { tempForm.BackColor = Color.Black; // Make sure everything is visible tempForm.Refresh(); - if (!isMetroApp) { + if (!IsMetroApp) { // Make sure the application window is active, so the colors & buttons are right ToForeground(); } @@ -1055,7 +1071,7 @@ namespace GreenshotPlugin.Core { if (capturedBitmap == null) { // Remove transparency, this will break the capturing if (!autoMode) { - tempForm.BackColor = Color.FromArgb(255, conf.DWMBackgroundColor.R, conf.DWMBackgroundColor.G, conf.DWMBackgroundColor.B); + tempForm.BackColor = Color.FromArgb(255, Conf.DWMBackgroundColor.R, Conf.DWMBackgroundColor.G, Conf.DWMBackgroundColor.B); } else { Color colorizationColor = DWM.ColorizationColor; // Modify by losing the transparency and increasing the intensity (as if the background color is white) @@ -1064,7 +1080,7 @@ namespace GreenshotPlugin.Core { } // Make sure everything is visible tempForm.Refresh(); - if (!isMetroApp) { + if (!IsMetroApp) { // Make sure the application window is active, so the colors & buttons are right ToForeground(); } @@ -1077,7 +1093,7 @@ namespace GreenshotPlugin.Core { // Not needed for Windows 8 if (!Environment.OSVersion.IsWindows8OrLater()) { // Only if the Inivalue is set, not maximized and it's not a tool window. - if (conf.WindowCaptureRemoveCorners && !Maximised && (ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) == 0) { + if (Conf.WindowCaptureRemoveCorners && !Maximised && (ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) == 0) { // Remove corners if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat)) { LOG.Debug("Changing pixelformat to Alpha for the RemoveCorners"); @@ -1122,8 +1138,8 @@ namespace GreenshotPlugin.Core { /// The bitmap to remove the corners from. private void RemoveCorners(Bitmap image) { using (IFastBitmap fastBitmap = FastBitmap.Create(image)) { - for (int y = 0; y < conf.WindowCornerCutShape.Count; y++) { - for (int x = 0; x < conf.WindowCornerCutShape[y]; x++) { + for (int y = 0; y < Conf.WindowCornerCutShape.Count; y++) { + for (int x = 0; x < Conf.WindowCornerCutShape[y]; x++) { fastBitmap.SetColorAt(x, y, Color.Transparent); fastBitmap.SetColorAt(image.Width-1-x, y, Color.Transparent); fastBitmap.SetColorAt(image.Width-1-x, image.Height-1-y, Color.Transparent); @@ -1230,7 +1246,7 @@ namespace GreenshotPlugin.Core { /// /// Helper method to get the Border size for GDI Windows /// - /// out Rectangle + /// out Size /// bool true if it worked private bool GetBorderSize(out Size size) { WindowInfo windowInfo = new WindowInfo(); @@ -1281,7 +1297,7 @@ namespace GreenshotPlugin.Core { return false; } - foreach (string excludeProcess in excludeProcessesFromFreeze) { + foreach (string excludeProcess in ExcludeProcessesFromFreeze) { if (titleOrProcessname.ToLower().Contains(excludeProcess)) { return false; } @@ -1409,7 +1425,7 @@ namespace GreenshotPlugin.Core { /// /// The Window Handle public WindowDetails(IntPtr hWnd) { - this.hWnd = hWnd; + this._hWnd = hWnd; } /// @@ -1419,7 +1435,7 @@ namespace GreenshotPlugin.Core { public static WindowDetails GetActiveWindow() { IntPtr hWnd = User32.GetForegroundWindow(); if (hWnd != null && hWnd != IntPtr.Zero) { - if (ignoreHandles.Contains(hWnd)) { + if (IgnoreHandles.Contains(hWnd)) { return GetDesktopWindow(); } @@ -1439,7 +1455,7 @@ namespace GreenshotPlugin.Core { public bool IsGreenshot { get { try { - if (!isMetroApp) { + if (!IsMetroApp) { using (Process thisWindowProcess = Process) { return "Greenshot".Equals(thisWindowProcess.MainModule.FileVersionInfo.ProductName); } @@ -1470,7 +1486,7 @@ namespace GreenshotPlugin.Core { /// /// Get all the top level windows, with matching classname /// - /// List with all the top level windows + /// List WindowDetails with all the top level windows public static List GetAllWindows(string classname) { return new WindowsEnumerator().GetWindows(IntPtr.Zero, classname).Items; } @@ -1478,7 +1494,6 @@ namespace GreenshotPlugin.Core { /// /// Recursive "find children which" /// - /// Window to look into /// point to check for /// public WindowDetails FindChildUnderPoint(Point point) { @@ -1507,7 +1522,7 @@ namespace GreenshotPlugin.Core { /// /// Get all the visible top level windows /// - /// List with all the visible top level windows + /// List WindowDetails with all the visible top level windows public static List GetVisibleWindows() { List windows = new List(); Rectangle screenBounds = WindowCapture.GetScreenBounds(); @@ -1542,7 +1557,7 @@ namespace GreenshotPlugin.Core { /// Get the WindowDetails for all Metro Apps /// These are all Windows with Classname "Windows.UI.Core.CoreWindow" /// - /// List with visible metro apps + /// List WindowDetails with visible metro apps public static List GetMetroApps() { List metroApps = new List(); // if the appVisibility != null we have Windows 8. @@ -1582,7 +1597,7 @@ namespace GreenshotPlugin.Core { /// /// Get all the top level windows /// - /// List with all the top level windows + /// List WindowDetails with all the top level windows public static List GetTopLevelWindows() { List windows = new List(); var possibleTopLevelWindows = GetMetroApps(); @@ -1660,7 +1675,7 @@ namespace GreenshotPlugin.Core { /// Helper method to "active" all windows that are not in the supplied list. /// One should preferably call "GetVisibleWindows" for the oldWindows. /// - /// List with old windows + /// List WindowDetails with old windows public static void ActiveNewerWindows(List oldWindows) { List windowsAfter = GetVisibleWindows(); foreach(WindowDetails window in windowsAfter) { diff --git a/GreenshotPlugin/UnmanagedHelpers/DWM.cs b/GreenshotPlugin/UnmanagedHelpers/DWM.cs index 7a5c77b72..36950eca4 100644 --- a/GreenshotPlugin/UnmanagedHelpers/DWM.cs +++ b/GreenshotPlugin/UnmanagedHelpers/DWM.cs @@ -130,7 +130,7 @@ namespace GreenshotPlugin.UnmanagedHelpers { /// Helper method for an easy DWM check /// /// bool true if DWM is available AND active - public static bool isDWMEnabled() { + public static bool IsDwmEnabled() { // According to: http://technet.microsoft.com/en-us/subscriptions/aa969538%28v=vs.85%29.aspx // And: http://msdn.microsoft.com/en-us/library/windows/desktop/aa969510%28v=vs.85%29.aspx // DMW is always enabled on Windows 8! So return true and save a check! ;-) diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs.cs b/GreenshotPlugin/UnmanagedHelpers/Structs.cs index e0e3cadcb..b3a8919a5 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs.cs @@ -25,17 +25,17 @@ using System.Runtime.InteropServices; namespace GreenshotPlugin.UnmanagedHelpers { [StructLayout(LayoutKind.Sequential), Serializable()] public struct SIZE { - public int width; - public int height; + public int Width; + public int Height; public SIZE(Size size) : this(size.Width, size.Height) { } public SIZE(int width, int height) { - this.width = width; - this.height = height; + Width = width; + Height = height; } public Size ToSize() { - return new Size(width, height); + return new Size(Width, Height); } } [StructLayout(LayoutKind.Sequential), Serializable()] diff --git a/appveyor12.yml b/appveyor12.yml index 05ac9b5b6..5c63431bf 100644 --- a/appveyor12.yml +++ b/appveyor12.yml @@ -67,12 +67,15 @@ deploy: auth_token: secure: 4sYcNGg7byBFtR7EkJHS8d3H3qP0u0LodlJWCV7g/4jEyv3vvVxqzh19zZ6Zgrf1 prerelease: true + draft: true on: build_type: UNSTABLE - provider: GitHub tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION) auth_token: secure: 4sYcNGg7byBFtR7EkJHS8d3H3qP0u0LodlJWCV7g/4jEyv3vvVxqzh19zZ6Zgrf1 + prerelease: false + draft: true on: build_type: RELEASE notifications: