diff --git a/Greenshot/Helpers/CaptureHelper.cs b/Greenshot/Helpers/CaptureHelper.cs
index a3c12e21a..20de9b114 100644
--- a/Greenshot/Helpers/CaptureHelper.cs
+++ b/Greenshot/Helpers/CaptureHelper.cs
@@ -27,7 +27,6 @@ using System.Drawing.Printing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
-
using Greenshot.Configuration;
using Greenshot.Destinations;
using Greenshot.Drawing;
@@ -37,6 +36,7 @@ using Greenshot.Plugin;
using GreenshotPlugin.Core;
using GreenshotPlugin.UnmanagedHelpers;
using Greenshot.IniFile;
+using Greenshot.Interop;
namespace Greenshot.Helpers {
///
@@ -410,6 +410,13 @@ namespace Greenshot.Helpers {
private Thread PrepareForCaptureWithFeedback() {
windows = new List();
+ // If the App Launcher is visisble, no other windows are active
+ WindowDetails appLauncherWindow = WindowDetails.GetAppLauncher();
+ if (appLauncherWindow != null && appLauncherWindow.Visible) {
+ windows.Add(appLauncherWindow);
+ return null;
+ }
+
Thread getWindowDetailsThread = new Thread (delegate() {
// Start Enumeration of "active" windows
List allWindows = WindowDetails.GetMetroApps();
@@ -733,7 +740,7 @@ namespace Greenshot.Helpers {
windowCaptureMode = WindowCaptureMode.Screen;
// Change to GDI, if allowed
- if (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);
@@ -744,12 +751,12 @@ namespace Greenshot.Helpers {
// Change to DWM, if enabled and allowed
if (dwmEnabled) {
- if (WindowCapture.isDWMAllowed(process)) {
+ if (windowToCapture.isMetroApp || WindowCapture.isDWMAllowed(process)) {
windowCaptureMode = WindowCaptureMode.Aero;
}
}
} else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) {
- if (!dwmEnabled || !WindowCapture.isDWMAllowed(process)) {
+ if (!dwmEnabled || (!windowToCapture.isMetroApp && !WindowCapture.isDWMAllowed(process))) {
// Take default screen
windowCaptureMode = WindowCaptureMode.Screen;
// Change to GDI, if allowed
@@ -828,7 +835,7 @@ namespace Greenshot.Helpers {
break;
case WindowCaptureMode.Aero:
case WindowCaptureMode.AeroTransparent:
- if (WindowCapture.isDWMAllowed(process)) {
+ if (windowToCapture.isMetroApp || WindowCapture.isDWMAllowed(process)) {
tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode);
}
if (tmpCapture != null) {
diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs
index 599d617ec..f879b60d7 100644
--- a/GreenshotPlugin/Core/WindowsHelper.cs
+++ b/GreenshotPlugin/Core/WindowsHelper.cs
@@ -30,6 +30,7 @@ using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using Greenshot.IniFile;
+using Greenshot.Interop;
using Greenshot.Plugin;
using GreenshotPlugin.UnmanagedHelpers;
@@ -160,6 +161,7 @@ namespace GreenshotPlugin.Core {
///
public class WindowDetails : IEquatable{
private const string METRO_WINDOWS_CLASS = "Windows.UI.Core.CoreWindow";
+ private const string METRO_APPLAUNCHER_CLASS = "ImmersiveLauncher";
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(WindowDetails));
private static Dictionary> classnameTree = new Dictionary>();
private static CoreConfiguration conf = IniConfig.GetIniSection();
@@ -182,12 +184,25 @@ namespace GreenshotPlugin.Core {
private WindowDetails parent = null;
private bool frozen = false;
+
+ public bool isApp {
+ get {
+ return METRO_WINDOWS_CLASS.Equals(ClassName);
+ }
+ }
+
+ public bool isAppLauncher {
+ get {
+ return METRO_APPLAUNCHER_CLASS.Equals(ClassName);
+ }
+ }
+
///
/// Check if this window is the window of a metro app
///
public bool isMetroApp {
get {
- return METRO_WINDOWS_CLASS.Equals(ClassName);
+ return isAppLauncher || isApp;
}
}
@@ -555,6 +570,9 @@ namespace GreenshotPlugin.Core {
///
public bool Iconic {
get {
+ if (isMetroApp) {
+ return !Visible;
+ }
return User32.IsIconic(this.hWnd) || Location.X <= -32000;
}
set {
@@ -579,6 +597,22 @@ namespace GreenshotPlugin.Core {
///
public bool Visible {
get {
+ if (isApp) {
+ // IAppVisibility appVisibility = COMWrapper.CreateInstance();
+ // if (appVisibility != null) {
+ // IntPtr monitor = User32.MonitorFromWindow(Handle, User32.MONITOR_DEFAULTTONULL);
+ // if (monitor != IntPtr.Zero) {
+ // LOG.DebugFormat("Monitor = {0}", monitor);
+ // MONITOR_APP_VISIBILITY monitorAppVisibility = appVisibility.GetAppVisibilityOnMonitor(monitor);
+ // LOG.DebugFormat("App visible: {0}", monitorAppVisibility);
+ // return monitorAppVisibility == MONITOR_APP_VISIBILITY.MAV_APP_VISIBLE;
+ // }
+ // }
+
+ }
+ if (isAppLauncher) {
+ return IsAppLauncherVisible;
+ }
return User32.IsWindowVisible(this.hWnd);
}
}
@@ -837,7 +871,7 @@ namespace GreenshotPlugin.Core {
// check if the capture fits
if (!doesCaptureFit) {
// if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
- if (WindowCapture.isGDIAllowed(Process)) {
+ if (!isMetroApp && WindowCapture.isGDIAllowed(Process)) {
// we return null which causes the capturing code to try another method.
return null;
}
@@ -1286,7 +1320,9 @@ namespace GreenshotPlugin.Core {
public bool IsGreenshot {
get {
try {
- return "Greenshot".Equals(Process.MainModule.FileVersionInfo.ProductName);
+ if (!isMetroApp) {
+ return "Greenshot".Equals(Process.MainModule.FileVersionInfo.ProductName);
+ }
} catch (Exception ex) {
LOG.Warn(ex);
}
@@ -1516,6 +1552,35 @@ namespace GreenshotPlugin.Core {
}
}
}
+
+ ///
+ /// Get the AppLauncher
+ ///
+ ///
+ public static WindowDetails GetAppLauncher() {
+ IntPtr appLauncher = User32.FindWindow("ImmersiveLauncher", null);
+ if (appLauncher != IntPtr.Zero) {
+ return new WindowDetails (appLauncher);
+ }
+ return null;
+ }
+
+ ///
+ /// Return true if the metro-app-launcher is visible
+ ///
+ ///
+ public static bool IsAppLauncherVisible {
+ get {
+ try {
+ IAppVisibility appVisibility = COMWrapper.CreateInstance();
+ if (appVisibility != null) {
+ return appVisibility.IsLauncherVisible;
+ }
+ } catch {}
+ return false;
+
+ }
+ }
}
#endregion
}
diff --git a/GreenshotPlugin/Interop/COMWrapper.cs b/GreenshotPlugin/Interop/COMWrapper.cs
index ff0cd07bf..eb0e7e476 100644
--- a/GreenshotPlugin/Interop/COMWrapper.cs
+++ b/GreenshotPlugin/Interop/COMWrapper.cs
@@ -57,6 +57,9 @@ namespace Greenshot.Interop {
#endregion
[DllImport("ole32.dll")]
static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);
+ // Converts failure HRESULTs to exceptions:
+ [DllImport("oleaut32", PreserveSig=false)]
+ static extern void GetActiveObject(ref Guid rclsid, IntPtr pvReserved, [MarshalAs(UnmanagedType.IUnknown)] out Object ppunk);
#region Construction
@@ -81,35 +84,102 @@ namespace Greenshot.Interop {
}
string progId = progIDAttribute.Value;
+ object comObject = null;
+
// Convert from clsid to Prog ID, if needed
if (progId.StartsWith("clsid:")) {
Guid guid = new Guid(progId.Substring(6));
int result = ProgIDFromCLSID(ref guid, out progId);
if (result != 0) {
- LOG.WarnFormat("Error {0} getting progId {1}", result, progIDAttribute.Value);
+ // Restore progId, as it's overwritten
+ progId = progIDAttribute.Value;
+
+ try {
+ GetActiveObject(ref guid, IntPtr.Zero, out comObject);
+ } catch (Exception) {
+ LOG.WarnFormat("Error {0} getting instance for class id {1}", result, progIDAttribute.Value);
+ }
+ if (comObject == null) {
+ LOG.WarnFormat("Error {0} getting progId {1}", result, progIDAttribute.Value);
+ }
} else {
LOG.InfoFormat("Mapped {0} to progId {1}", progIDAttribute.Value, progId);
}
}
- object comObject = null;
- try {
- comObject = Marshal.GetActiveObject(progId);
- } catch (COMException comE) {
- if (comE.ErrorCode == MK_E_UNAVAILABLE) {
- LOG.DebugFormat("No current instance of {0} object available.", progId);
- } else if (comE.ErrorCode == CO_E_CLASSSTRING) {
- LOG.WarnFormat("Unknown progId {0}", progId);
- } else {
- LOG.Warn("Error getting active object for " + progId, comE);
+ if (comObject == null) {
+ try {
+ comObject = Marshal.GetActiveObject(progId);
+ } catch (COMException comE) {
+ if (comE.ErrorCode == MK_E_UNAVAILABLE) {
+ LOG.DebugFormat("No current instance of {0} object available.", progId);
+ } else if (comE.ErrorCode == CO_E_CLASSSTRING) {
+ LOG.WarnFormat("Unknown progId {0}", progId);
+ } else {
+ LOG.Warn("Error getting active object for " + progIDAttribute.Value, comE);
+ }
+ } catch (Exception e) {
+ LOG.Warn("Error getting active object for " + progIDAttribute.Value, e);
}
- } catch (Exception e) {
- LOG.Warn("Error getting active object for " + progId, e);
}
if (comObject != null) {
- COMWrapper wrapper = new COMWrapper(comObject, type);
- return (T)wrapper.GetTransparentProxy();
+ if (comObject is IDispatch) {
+ COMWrapper wrapper = new COMWrapper(comObject, type);
+ return (T)wrapper.GetTransparentProxy();
+ } else {
+ return (T)comObject;
+ }
+ }
+ return default(T);
+ }
+
+ ///
+ /// A simple create instance, doesn't create a wrapper!!
+ ///
+ /// T
+ public static T CreateInstance() {
+ Type type = typeof(T);
+ if (null == type) {
+ throw new ArgumentNullException("type");
+ }
+ if (!type.IsInterface) {
+ throw new ArgumentException("The specified type must be an interface.", "type");
+ }
+
+ ComProgIdAttribute progIDAttribute = ComProgIdAttribute.GetAttribute(type);
+ if (null == progIDAttribute || null == progIDAttribute.Value || 0 == progIDAttribute.Value.Length) {
+ throw new ArgumentException("The specified type must define a ComProgId attribute.", "type");
+ }
+ string progId = progIDAttribute.Value;
+ Type comType = null;
+ if (progId.StartsWith("clsid:")) {
+ Guid guid = new Guid(progId.Substring(6));
+ try {
+ comType = Type.GetTypeFromCLSID(guid);
+ } catch (Exception ex) {
+ LOG.Warn("Error type for " + progId, ex);
+ }
+ } else {
+ try {
+ comType = Type.GetTypeFromProgID(progId, true);
+ } catch (Exception ex) {
+ LOG.Warn("Error type for " + progId, ex);
+ }
+ }
+ object comObject = null;
+ if (comType != null) {
+ try {
+ comObject = Activator.CreateInstance(comType);
+ if (comObject != null) {
+ LOG.DebugFormat("Created new instance of {0} object.", progId);
+ }
+ } catch (Exception e) {
+ LOG.Warn("Error creating object for " + progId, e);
+ }
+ }
+ if (comObject != null) {
+ return (T)comObject;
}
return default(T);
}
@@ -138,39 +208,59 @@ namespace Greenshot.Interop {
object comObject = null;
Type comType = null;
string progId = progIDAttribute.Value;
+ Guid guid = Guid.Empty;
// Convert from clsid to Prog ID, if needed
if (progId.StartsWith("clsid:")) {
- Guid guid = new Guid(progId.Substring(6));
+ guid = new Guid(progId.Substring(6));
int result = ProgIDFromCLSID(ref guid, out progId);
if (result != 0) {
- LOG.WarnFormat("Error {0} getting progId {1}", result, progIDAttribute.Value);
+ // Restore progId, as it's overwritten
+ progId = progIDAttribute.Value;
+ try {
+ GetActiveObject(ref guid, IntPtr.Zero, out comObject);
+ } catch (Exception) {
+ LOG.WarnFormat("Error {0} getting instance for class id {1}", result, progIDAttribute.Value);
+ }
+ if (comObject == null) {
+ LOG.WarnFormat("Error {0} getting progId {1}", result, progIDAttribute.Value);
+ }
} else {
LOG.InfoFormat("Mapped {0} to progId {1}", progIDAttribute.Value, progId);
}
}
- try {
- comObject = Marshal.GetActiveObject(progId);
- } catch (COMException comE) {
- if (comE.ErrorCode == MK_E_UNAVAILABLE) {
- LOG.DebugFormat("No current instance of {0} object available.", progId);
- } else if (comE.ErrorCode == CO_E_CLASSSTRING) {
- LOG.WarnFormat("Unknown progId {0} (application not installed)", progId);
- return default(T);
- } else {
- LOG.Warn("Error getting active object for " + progId, comE);
+ if (comObject == null) {
+ if (!progId.StartsWith("clsid:")) {
+ try {
+ comObject = Marshal.GetActiveObject(progId);
+ } catch (COMException comE) {
+ if (comE.ErrorCode == MK_E_UNAVAILABLE) {
+ LOG.DebugFormat("No current instance of {0} object available.", progId);
+ } else if (comE.ErrorCode == CO_E_CLASSSTRING) {
+ LOG.WarnFormat("Unknown progId {0} (application not installed)", progId);
+ return default(T);
+ } else {
+ LOG.Warn("Error getting active object for " + progId, comE);
+ }
+ } catch (Exception e) {
+ LOG.Warn("Error getting active object for " + progId, e);
+ }
}
- } catch (Exception e) {
- LOG.Warn("Error getting active object for " + progId, e);
}
+
// Did we get the current instance? If not, try to create a new
if (comObject == null) {
try {
comType = Type.GetTypeFromProgID(progId, true);
} catch (Exception ex) {
- LOG.Warn("Error type for " + progId, ex);
+ if (Guid.Empty != guid) {
+ comType = Type.GetTypeFromCLSID(guid);
+ } else {
+ LOG.Warn("Error type for " + progId, ex);
+ }
}
+
if (comType != null) {
try {
comObject = Activator.CreateInstance(comType);
@@ -183,8 +273,12 @@ namespace Greenshot.Interop {
}
}
if (comObject != null) {
- COMWrapper wrapper = new COMWrapper(comObject, type);
- return (T)wrapper.GetTransparentProxy();
+ if (comObject is IDispatch) {
+ COMWrapper wrapper = new COMWrapper(comObject, type);
+ return (T)wrapper.GetTransparentProxy();
+ } else {
+ return (T)comObject;
+ }
}
return default(T);
}
diff --git a/GreenshotPlugin/Interop/IAppVisibility.cs b/GreenshotPlugin/Interop/IAppVisibility.cs
index c5f96364e..963d94099 100644
--- a/GreenshotPlugin/Interop/IAppVisibility.cs
+++ b/GreenshotPlugin/Interop/IAppVisibility.cs
@@ -19,22 +19,24 @@
* along with this program. If not, see .
*/
using System;
+using System.Runtime.InteropServices;
using Greenshot.Interop;
-namespace GreenshotPlugin.Interop {
+namespace Greenshot.Interop {
// This is used for Windows 8 to see if the App Launcher is active
// See http://msdn.microsoft.com/en-us/library/windows/desktop/jj554119%28v=vs.85%29.aspx
- [ComProgId("7E5FE3D9-985F-4908-91F9-EE19F9FD1514")]
- public interface IAppVisibility : Common {
- //MONITOR_APP_VISIBILITY GetAppVisibilityOnMonitor(IntPtr hMonitor);
+ [ComProgId("clsid:7E5FE3D9-985F-4908-91F9-EE19F9FD1514")]
+ [ComImport, Guid("2246EA2D-CAEA-4444-A3C4-6DE827E44313"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IAppVisibility {
+ MONITOR_APP_VISIBILITY GetAppVisibilityOnMonitor(IntPtr hMonitor);
bool IsLauncherVisible {
get;
}
}
- //public enum MONITOR_APP_VISIBILITY {
- // MAV_UNKNOWN = 0, // The mode for the monitor is unknown
- // MAV_NO_APP_VISIBLE = 1,
- // MAV_APP_VISIBLE = 2
- //}
+ public enum MONITOR_APP_VISIBILITY {
+ MAV_UNKNOWN = 0, // The mode for the monitor is unknown
+ MAV_NO_APP_VISIBLE = 1,
+ MAV_APP_VISIBLE = 2
+ }
}
diff --git a/GreenshotPlugin/UnmanagedHelpers/User32.cs b/GreenshotPlugin/UnmanagedHelpers/User32.cs
index 886e5e808..10981d469 100644
--- a/GreenshotPlugin/UnmanagedHelpers/User32.cs
+++ b/GreenshotPlugin/UnmanagedHelpers/User32.cs
@@ -271,6 +271,11 @@ namespace GreenshotPlugin.UnmanagedHelpers {
public const int PW_DEFAULT = 0x00;
public const int PW_CLIENTONLY = 0x01;
+
+ // For MonitorFromWindow
+ public const int MONITOR_DEFAULTTONULL = 0;
+ public const int MONITOR_DEFAULTTOPRIMARY = 1;
+ public const int MONITOR_DEFAULTTONEAREST = 2;
///
/// Stop flashing. The system restores the window to its original state.
@@ -347,10 +352,14 @@ namespace GreenshotPlugin.UnmanagedHelpers {
public static extern bool SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("user32", SetLastError=true)]
public extern static uint GetWindowLong(IntPtr hwnd, int index);
- [DllImport("user32", SetLastError = true)]
- public static extern int SetWindowLong(IntPtr hWnd, int index, uint styleFlags);
[DllImport("user32", EntryPoint="GetWindowLongPtr", SetLastError=true)]
public extern static uint GetWindowLongPtr(IntPtr hwnd, int nIndex);
+ [DllImport("user32", SetLastError = true)]
+ public static extern int SetWindowLong(IntPtr hWnd, int index, uint styleFlags);
+ [DllImport("user32", SetLastError = true)]
+ public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
+ [DllImport("user32", SetLastError = true)]
+ public static extern IntPtr MonitorFromRect([In] ref RECT lprc, uint dwFlags);
///
/// Wrapper for the GetWindowLong which decides if the system is 64-bit or not and calls the right one.