mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-27 23:19:13 +08:00
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:
parent
5ff146bc69
commit
c241d48df3
@ -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)]
|
||||
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)]
|
||||
public static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
|
||||
|
||||
@ -606,6 +784,9 @@ namespace WindowWalker.Components
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool IsWindowVisible(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool IsWindow(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
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")]
|
||||
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")]
|
||||
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)]
|
||||
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")]
|
||||
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
|
||||
|
||||
|
@ -94,22 +94,11 @@ namespace WindowWalker.Components
|
||||
{
|
||||
Window newWindow = new Window(hwnd);
|
||||
|
||||
if (windows.Select(x => x.Title).Contains(newWindow.Title))
|
||||
{
|
||||
if (newWindow.ProcessName.ToLower().Equals("applicationframehost.exe"))
|
||||
{
|
||||
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"))
|
||||
if (newWindow.IsWindow && newWindow.Visible && newWindow.IsOwner &&
|
||||
(!newWindow.IsToolWindow || newWindow.IsAppWindow ) && !newWindow.TaskListDeleted &&
|
||||
newWindow.ClassName != "Windows.UI.Core.CoreWindow")
|
||||
{
|
||||
windows.Add(newWindow);
|
||||
|
||||
OnOpenWindowsUpdate?.Invoke(this, new SearchController.SearchResultUpdateEventArgs());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -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>
|
||||
/// Gets a value indicating whether returns true if the window is minimized
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user