Better app listing like Alt-Tab supports UWP apps and hidden apps running including in another Virtual Desktops (#1956)

* Better app listing like Alt-Tab supports UWP apps and hidden apps running in another virtual desktop just like Windows Alt-Tab

* Modified not to hide cloaked apps i.e. also show apps running in another virtual desktop

* Improved listing apps, with readability and reusable abstract properties.
Including a function to detect cloaked UWP apps for future use.
This commit is contained in:
vhanla 2020-04-07 17:02:14 -05:00 committed by GitHub
parent 5ff146bc69
commit c241d48df3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 271 additions and 14 deletions

View File

@ -594,9 +594,187 @@ namespace WindowWalker.Components
} }
} }
/// <summary>
/// GetWindow relationship between the specified window and the window whose handle is to be retrieved.
/// </summary>
public enum GetWindowCmd : uint
{
/// <summary>
/// The retrieved handle identifies the window of the same type that is highest in the Z order.
/// </summary>
GW_HWNDFIRST = 0,
/// <summary>
/// The retrieved handle identifies the window of the same type that is lowest in the Z order.
/// </summary>
GW_HWNDLAST = 1,
/// <summary>
/// The retrieved handle identifies the window below the specified window in the Z order.
/// </summary>
GW_HWNDNEXT = 2,
/// <summary>
/// The retrieved handle identifies the window above the specified window in the Z order.
/// </summary>
GW_HWNDPREV = 3,
/// <summary>
/// The retrieved handle identifies the specified window's owner window, if any.
/// </summary>
GW_OWNER = 4,
/// <summary>
/// The retrieved handle identifies the child window at the top of the Z order, if the specified window
/// is a parent window.
/// </summary>
GW_CHILD = 5,
/// <summary>
/// The retrieved handle identifies the enabled popup window owned by the specified window.
/// </summary>
GW_ENABLEDPOPUP = 6
}
/// <summary>
/// GetWindowLong index to retrieves the extended window styles.
/// </summary>
public const int GWL_EXSTYLE = -20;
/// <summary>
/// The following are the extended window styles
/// </summary>
[Flags]
public enum ExtendedWindowStyles : UInt32
{
/// <summary>
/// The window has a double border; the window can, optionally, be created with a title bar by specifying
/// the WS_CAPTION style in the dwStyle parameter.
/// </summary>
WS_EX_DLGMODALFRAME = 0X0001,
/// <summary>
/// The child window created with this style does not send the WM_PARENTNOTIFY message to its parent window
/// when it is created or destroyed.
/// </summary>
WS_EX_NOPARENTNOTIFY = 0X0004,
/// <summary>
/// The window should be placed above all non-topmost windows and should stay above all non-topmost windows
/// and should stay above them, even when the window is deactivated.
/// </summary>
WS_EX_TOPMOST = 0X0008,
/// <summary>
/// The window accepts drag-drop files.
/// </summary>
WS_EX_ACCEPTFILES = 0x0010,
/// <summary>
/// The window should not be painted until siblings beneath the window (that were created by the same thread)
/// have been painted.
/// </summary>
WS_EX_TRANSPARENT = 0x0020,
/// <summary>
/// The window is a MDI child window.
/// </summary>
WS_EX_MDICHILD = 0x0040,
/// <summary>
/// The window is intended to be used as a floating toolbar. A tool window has a title bar that is shorter
/// than a normal title bar, and the window title is drawn using a smaller font. A tool window does not
/// appear in the taskbar or in the dialog that appears when the user presses ALT+TAB.
/// </summary>
WS_EX_TOOLWINDOW = 0x0080,
/// <summary>
/// The window has a border with a raised edge.
/// </summary>
WS_EX_WINDOWEDGE = 0x0100,
/// <summary>
/// The window has a border with a sunken edge.
/// </summary>
WS_EX_CLIENTEDGE = 0x0200,
/// <summary>
/// The title bar of the window includes a question mark.
/// </summary>
WS_EX_CONTEXTHELP = 0x0400,
/// <summary>
/// The window has generic "right-aligned" properties. This depends on the window class. This style has
/// an effect only if the shell language supports reading-order alignment, otherwise is ignored.
/// </summary>
WS_EX_RIGHT = 0x1000,
/// <summary>
/// The window has generic left-aligned properties. This is the default.
/// </summary>
WS_EX_LEFT = 0x0,
/// <summary>
/// If the shell language supports reading-order alignment, the window text is displayed using right-to-left
/// reading-order properties. For other languages, the styles is ignored.
/// </summary>
WS_EX_RTLREADING = 0x2000,
/// <summary>
/// The window text is displayed using left-to-right reading-order properties. This is the default.
/// </summary>
WS_EX_LTRREADING = 0x0,
/// <summary>
/// If the shell language supports reading order alignment, the vertical scroll bar (if present) is to
/// the left of the client area. For other languages, the style is ignored.
/// </summary>
WS_EX_LEFTSCROLLBAR = 0x4000,
/// <summary>
/// The vertical scroll bar (if present) is to the right of the client area. This is the default.
/// </summary>
WS_EX_RIGHTSCROLLBAR = 0x0,
/// <summary>
/// The window itself contains child windows that should take part in dialog box, navigation. If this
/// style is specified, the dialog manager recurses into children of this window when performing
/// navigation operations such as handling tha TAB key, an arrow key, or a keyboard mnemonic.
/// </summary>
WS_EX_CONTROLPARENT = 0x10000,
/// <summary>
/// The window has a three-dimensional border style intended to be used for items that do not accept
/// user input.
/// </summary>
WS_EX_STATICEDGE = 0x20000,
/// <summary>
/// Forces a top-level window onto the taskbar when the window is visible.
/// </summary>
WS_EX_APPWINDOW = 0x40000,
/// <summary>
/// The window is an overlapped window.
/// </summary>
WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
/// <summary>
/// The window is palette window, which is a modeless dialog box that presents an array of commands.
/// </summary>
WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
/// <summary>
/// The window is a layered window. This style cannot be used if the window has a class style of either
/// CS_OWNDC or CS_CLASSDC. Only for top level window before Windows 8, and child windows from Windows 8.
/// </summary>
WS_EX_LAYERED = 0x80000,
/// <summary>
/// The window does not pass its window layout to its child windows.
/// </summary>
WS_EX_NOINHERITLAYOUT = 0x100000,
/// <summary>
/// If the shell language supports reading order alignment, the horizontal origin of the window is on the
/// right edge. Increasing horizontal values advance to the left.
/// </summary>
WS_EX_LAYOUTRTL = 0x400000,
/// <summary>
/// Paints all descendants of a window in bottom-to-top painting order using double-buffering.
/// Bottom-to-top painting order allows a descendent window to have translucency (alpha) and
/// transparency (color-key) effects, but only if the descendent window also has the WS_EX_TRANSPARENT
/// bit set. Double-buffering allows the window and its descendents to be painted without flicker.
/// </summary>
WS_EX_COMPOSITED = 0x2000000,
/// <summary>
/// A top-level window created with this style does not become the foreground window when the user
/// clicks it. The system does not bring this window to the foreground when the user minimizes or closes
/// the foreground window.
/// </summary>
WS_EX_NOACTIVATE = 0x8000000
}
[DllImport("user32.dll", CharSet = CharSet.Unicode)] [DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int EnumWindows(CallBackPtr callPtr, int lPar); public static extern int EnumWindows(CallBackPtr callPtr, int lPar);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCmd uCmd);
[DllImport("user32.dll", SetLastError = true)]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Unicode)] [DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount); public static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
@ -606,6 +784,9 @@ namespace WindowWalker.Components
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd); public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")] [DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags); public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags);
@ -633,6 +814,9 @@ namespace WindowWalker.Components
[DllImport("psapi.dll")] [DllImport("psapi.dll")]
public static extern uint GetProcessImageFileName(IntPtr hProcess, [Out] StringBuilder lpImageFileName, [In] [MarshalAs(UnmanagedType.U4)] int nSize); public static extern uint GetProcessImageFileName(IntPtr hProcess, [Out] StringBuilder lpImageFileName, [In] [MarshalAs(UnmanagedType.U4)] int nSize);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetProp(IntPtr hWnd, string lpString);
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId); public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
@ -642,6 +826,9 @@ namespace WindowWalker.Components
[DllImport("dwmapi.dll", PreserveSig = false)] [DllImport("dwmapi.dll", PreserveSig = false)]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize); public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out int pvAttribute, int cbAttribute);
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

View File

@ -94,22 +94,11 @@ namespace WindowWalker.Components
{ {
Window newWindow = new Window(hwnd); Window newWindow = new Window(hwnd);
if (windows.Select(x => x.Title).Contains(newWindow.Title)) if (newWindow.IsWindow && newWindow.Visible && newWindow.IsOwner &&
{ (!newWindow.IsToolWindow || newWindow.IsAppWindow ) && !newWindow.TaskListDeleted &&
if (newWindow.ProcessName.ToLower().Equals("applicationframehost.exe")) newWindow.ClassName != "Windows.UI.Core.CoreWindow")
{
windows.Remove(windows.Where(x => x.Title == newWindow.Title).First());
}
return true;
}
if ((newWindow.Visible && !newWindow.ProcessName.ToLower().Equals("iexplore.exe")) ||
(newWindow.ProcessName.ToLower().Equals("iexplore.exe") && newWindow.ClassName == "TabThumbnailWindow"))
{ {
windows.Add(newWindow); windows.Add(newWindow);
OnOpenWindowsUpdate?.Invoke(this, new SearchController.SearchResultUpdateEventArgs());
} }
return true; return true;

View File

@ -168,6 +168,87 @@ namespace WindowWalker.Components
} }
} }
/// <summary>
/// Determines whether the specified window handle identifies an existing window.
/// </summary>
public bool IsWindow
{
get
{
return InteropAndHelpers.IsWindow(Hwnd);
}
}
/// <summary>
/// Get a value indicating whether is the window GWL_EX_STYLE is a toolwindow
/// </summary>
public bool IsToolWindow
{
get
{
return (InteropAndHelpers.GetWindowLong(Hwnd, InteropAndHelpers.GWL_EXSTYLE) &
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_TOOLWINDOW) ==
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_TOOLWINDOW;
}
}
/// <summary>
/// Get a value indicating whether the window GWL_EX_STYLE is an appwindow
/// </summary>
public bool IsAppWindow
{
get
{
return (InteropAndHelpers.GetWindowLong(Hwnd, InteropAndHelpers.GWL_EXSTYLE) &
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_APPWINDOW) ==
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_APPWINDOW;
}
}
/// <summary>
/// Get a value indicating whether the window has ITaskList_Deleted property
/// </summary>
public bool TaskListDeleted
{
get
{
return InteropAndHelpers.GetProp(Hwnd, "ITaskList_Deleted") != IntPtr.Zero;
}
}
/// <summary>
/// Get a value indicating whether the app is a cloaked UWP app
/// </summary>
public bool IsUWPCloaked
{
get
{
return (this.IsWindowCloaked() && this.ClassName == "ApplicationFrameWindow");
}
}
/// <summary>
/// Determines whether the specified windows is the owner
/// </summary>
public bool IsOwner
{
get
{
return InteropAndHelpers.GetWindow(Hwnd, InteropAndHelpers.GetWindowCmd.GW_OWNER) != null;
}
}
/// <summary>
/// Gets a value indicating whether is the window cloaked. To detect UWP apps in background or win32 apps running in another virtual desktop
/// </summary>
public bool IsWindowCloaked()
{
int isCloaked = 0;
const int DWMWA_CLOAKED = 14;
InteropAndHelpers.DwmGetWindowAttribute(this.hwnd, DWMWA_CLOAKED, out isCloaked, sizeof(int));
return isCloaked != 0;
}
/// <summary> /// <summary>
/// Gets a value indicating whether returns true if the window is minimized /// Gets a value indicating whether returns true if the window is minimized
/// </summary> /// </summary>