Some more changes for BUG-2017, this simplified some of the code and adds different logic for Windows 10 apps.

This commit is contained in:
Robin 2016-09-04 22:23:42 +02:00
commit c0d18c952c
3 changed files with 43 additions and 34 deletions

View file

@ -826,7 +826,7 @@ namespace Greenshot.Forms {
if (_showDebugInfo && _selectedCaptureWindow != null) if (_showDebugInfo && _selectedCaptureWindow != null)
{ {
string title = string.Format("#{0:X}{1}{2}", _selectedCaptureWindow.Handle.ToInt64(), _selectedCaptureWindow.Text.Length > 0 ? " - ": "", _selectedCaptureWindow.Text); string title = string.Format("#{0:X} - {1}", _selectedCaptureWindow.Handle.ToInt64(), _selectedCaptureWindow.Text.Length > 0 ? _selectedCaptureWindow.Text : _selectedCaptureWindow.Process.ProcessName);
PointF debugLocation = new PointF(fixedRect.X, fixedRect.Y); PointF debugLocation = new PointF(fixedRect.X, fixedRect.Y);
graphics.DrawString(title, sizeFont, Brushes.DarkOrange, debugLocation); graphics.DrawString(title, sizeFont, Brushes.DarkOrange, debugLocation);
} }

View file

@ -461,9 +461,11 @@ namespace Greenshot.Helpers {
return null; return null;
} }
Thread getWindowDetailsThread = new Thread(RetrieveWindowDetails); Thread getWindowDetailsThread = new Thread(RetrieveWindowDetails)
getWindowDetailsThread.Name = "Retrieve window details"; {
getWindowDetailsThread.IsBackground = true; Name = "Retrieve window details",
IsBackground = true
};
getWindowDetailsThread.Start(); getWindowDetailsThread.Start();
return getWindowDetailsThread; return getWindowDetailsThread;
} }
@ -471,21 +473,7 @@ namespace Greenshot.Helpers {
private void RetrieveWindowDetails() { private void RetrieveWindowDetails() {
LOG.Debug("start RetrieveWindowDetails"); LOG.Debug("start RetrieveWindowDetails");
// Start Enumeration of "active" windows // Start Enumeration of "active" windows
List<WindowDetails> allWindows = new List<WindowDetails>(WindowDetails.GetMetroApps()); foreach (var window in WindowDetails.GetVisibleWindows()) {
allWindows.AddRange(WindowDetails.GetAllWindows());
foreach (WindowDetails window in allWindows) {
// Window should be visible and not ourselves
if (!window.Visible) {
continue;
}
// Skip empty
Rectangle windowRectangle = window.WindowRectangle;
Size windowSize = windowRectangle.Size;
if (windowSize.Width == 0 || windowSize.Height == 0) {
continue;
}
// Make sure the details are retrieved once // Make sure the details are retrieved once
window.FreezeDetails(); window.FreezeDetails();

View file

@ -140,10 +140,11 @@ namespace GreenshotPlugin.Core {
/// Provides details about a Window returned by the enumeration /// Provides details about a Window returned by the enumeration
/// </summary> /// </summary>
public class WindowDetails : IEquatable<WindowDetails>{ public class WindowDetails : IEquatable<WindowDetails>{
private const string MetroWindowsClass = "Windows.UI.Core.CoreWindow"; // Windows 10 uses ApplicationFrameWindow private const string MetroWindowsClass = "Windows.UI.Core.CoreWindow"; //Used for Windows 8(.1)
private const string FramedAppClass = "ApplicationFrameWindow"; // Windows 10 uses ApplicationFrameWindow
private const string MetroApplauncherClass = "ImmersiveLauncher"; private const string MetroApplauncherClass = "ImmersiveLauncher";
private const string MetroGutterClass = "ImmersiveGutter"; private const string MetroGutterClass = "ImmersiveGutter";
private static readonly IList<string> IgnoreClasses = new List<string>(new[] { "Progman", "XLMAIN", "Button", "Dwm" }); //"MS-SDIa" private static readonly IList<string> IgnoreClasses = new List<string>(new[] { "Progman", "Button", "Dwm" }); //"MS-SDIa"
private static readonly ILog Log = LogManager.GetLogger(typeof(WindowDetails)); private static readonly ILog Log = LogManager.GetLogger(typeof(WindowDetails));
private static readonly CoreConfiguration Conf = IniConfig.GetIniSection<CoreConfiguration>(); private static readonly CoreConfiguration Conf = IniConfig.GetIniSection<CoreConfiguration>();
@ -187,6 +188,12 @@ namespace GreenshotPlugin.Core {
/// </summary> /// </summary>
public bool IsApp => MetroWindowsClass.Equals(ClassName); public bool IsApp => MetroWindowsClass.Equals(ClassName);
/// <summary>
/// This checks if the window is a Windows 10 App
/// For Windows 10 apps are hosted inside "ApplicationFrameWindow"
/// </summary>
public bool IsWin10App => FramedAppClass.Equals(ClassName);
/// <summary> /// <summary>
/// Check if the window is the metro gutter (sizeable separator) /// Check if the window is the metro gutter (sizeable separator)
/// </summary> /// </summary>
@ -843,7 +850,7 @@ namespace GreenshotPlugin.Core {
/// <param name="p">Point with the coordinates to check</param> /// <param name="p">Point with the coordinates to check</param>
/// <returns>true if the point lies within</returns> /// <returns>true if the point lies within</returns>
public bool Contains(Point p) { public bool Contains(Point p) {
return WindowRectangle.Contains(Cursor.Position); return WindowRectangle.Contains(p);
} }
/// <summary> /// <summary>
@ -1484,6 +1491,13 @@ namespace GreenshotPlugin.Core {
if (!Contains(point)) { if (!Contains(point)) {
return null; return null;
} }
var rect = WindowRectangle;
// If the mouse it at the edge, take the whole window
if (rect.X == point.X || rect.Y == point.Y || rect.Right == point.X || rect.Bottom == point.Y)
{
return this;
}
// Look into the child windows
foreach(var childWindow in Children) { foreach(var childWindow in Children) {
if (childWindow.Contains(point)) { if (childWindow.Contains(point)) {
return childWindow.FindChildUnderPoint(point); return childWindow.FindChildUnderPoint(point);
@ -1509,15 +1523,15 @@ namespace GreenshotPlugin.Core {
/// <param name="window"></param> /// <param name="window"></param>
/// <param name="screenBounds"></param> /// <param name="screenBounds"></param>
/// <returns></returns> /// <returns></returns>
private static bool IsVisibleTopLevel(WindowDetails window, Rectangle screenBounds) private static bool IsVisible(WindowDetails window, Rectangle screenBounds)
{ {
// Ignore windows without title // Ignore invisible
if (window.Text.Length == 0) if (!window.Visible)
{ {
return false; return false;
} }
// Ignore invisible // Ignore minizied
if (!window.Visible) if (window.Iconic)
{ {
return false; return false;
} }
@ -1525,13 +1539,20 @@ namespace GreenshotPlugin.Core {
{ {
return false; return false;
} }
// Windows without size // On windows which are visible on the screen
Rectangle windowRect = window.WindowRectangle; var windowRect = window.WindowRectangle;
windowRect.Intersect(screenBounds); windowRect.Intersect(screenBounds);
if (windowRect.Size.IsEmpty) if (windowRect.IsEmpty)
{ {
return false; return false;
} }
// Skip everything which is not rendered "normally", trying to fix BUG-2017
var exWindowStyle = window.ExtendedWindowStyle;
if (!window.IsApp && !window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0)
{
return false;
}
return true; return true;
} }
@ -1542,14 +1563,14 @@ namespace GreenshotPlugin.Core {
public static IEnumerable<WindowDetails> GetVisibleWindows() { public static IEnumerable<WindowDetails> GetVisibleWindows() {
Rectangle screenBounds = WindowCapture.GetScreenBounds(); Rectangle screenBounds = WindowCapture.GetScreenBounds();
foreach(var window in GetMetroApps()) { foreach(var window in GetMetroApps()) {
if (IsVisibleTopLevel(window, screenBounds)) if (IsVisible(window, screenBounds))
{ {
yield return window; yield return window;
} }
} }
foreach (var window in GetAllWindows()) foreach (var window in GetAllWindows())
{ {
if (IsVisibleTopLevel(window, screenBounds)) if (IsVisible(window, screenBounds))
{ {
yield return window; yield return window;
} }
@ -1625,8 +1646,8 @@ namespace GreenshotPlugin.Core {
{ {
return false; return false;
} }
// Skip everything which is not rendered "normally", trying to fix // Skip everything which is not rendered "normally", trying to fix BUG-2017
if (!window.IsApp && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0) if (!window.IsApp && !window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0)
{ {
return false; return false;
} }