I have investigated with Spy++ and neither EnumWindows
nor EnumChildWindows
retrieve the handles of the root owners of full screen UWP windows. However EnumChildWindows
retrieves their child windows, and each UWP window has a child window whose class name is ApplicationFrameInputSinkWindow (and other child windows). Then, you can retrive the root owner window with GetAncestor.
So, to retrieve "standard" windows, you could call EnumWindows.
But to retrieve full screen UWP windows:
This sample shows how to use both EnumWindows
and EnumChildWindows
to enumerate all "ALT+TAB windows", even full-screen UWP windows. These are listed in a Form with a two-column DataGridView and the window handle corresponding to the row the user clicks on is retrieved.
const int GWL_EXSTYLE = -20;
const uint DWMWA_CLOAKED = 14;
const uint DWM_CLOAKED_SHELL = 0x00000002;
const uint GA_ROOTOWNER = 3;
const uint WS_EX_TOOLWINDOW = 0x00000080;
const uint WS_EX_TOPMOST = 0x00000008;
const uint WS_EX_NOACTIVATE = 0x08000000;
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.MultiSelect = false;
dataGridView1.ReadOnly = true;
dataGridView1.Click += dataGridView1_Click;
EnumWindows(GetAltTabWindows, IntPtr.Zero);
EnumChildWindows(GetDesktopWindow(), GetFullScreenUWPWindows, IntPtr.Zero);
}
private bool GetAltTabWindows(IntPtr hWnd, IntPtr lparam)
{
if (IsAltTabWindow(hWnd))
AddWindowToGrid(hWnd);
return true;
}
private bool GetFullScreenUWPWindows(IntPtr hWnd, IntPtr lparam)
{
// Check only the windows whose class name is ApplicationFrameInputSinkWindow
StringBuilder className = new StringBuilder(1024);
GetClassName(hWnd, className, className.Capacity);
if (className.ToString() != "ApplicationFrameInputSinkWindow")
return true;
// Get the root owner of the window
IntPtr rootOwner = GetAncestor(hWnd, GA_ROOTOWNER);
if (IsFullScreenUWPWindows(rootOwner))
AddWindowToGrid(rootOwner);
return true;
}
private bool IsAltTabWindow(IntPtr hWnd)
{
// The window must be visible
if (!IsWindowVisible(hWnd))
return false;
// The window must be a root owner
if (GetAncestor(hWnd, GA_ROOTOWNER) != hWnd)
return false;
// The window must not be cloaked by the shell
DwmGetWindowAttribute(hWnd, DWMWA_CLOAKED, out uint cloaked, sizeof(uint));
if (cloaked == DWM_CLOAKED_SHELL)
return false;
// The window must not have the extended style WS_EX_TOOLWINDOW
uint style = GetWindowLong(hWnd, GWL_EXSTYLE);
if ((style & WS_EX_TOOLWINDOW) != 0)
return false;
return true;
}
private bool IsFullScreenUWPWindows(IntPtr hWnd)
{
// Get the extended style of the window
uint style = GetWindowLong(hWnd, GWL_EXSTYLE);
// The window must have the extended style WS_EX_TOPMOST
if ((style & WS_EX_TOPMOST) == 0)
return false;
// The window must not have the extended style WS_EX_NOACTIVATE
if ((style & WS_EX_NOACTIVATE) != 0)
return false;
// The window must not have the extended style WS_EX_TOOLWINDOW
if ((style & WS_EX_TOOLWINDOW) != 0)
return false;
return true;
}
private void AddWindowToGrid(IntPtr hWnd)
{
StringBuilder windowText = new StringBuilder(1024);
GetWindowText(hWnd, windowText, windowText.Capacity);
var strTitle = windowText.ToString();
var strHandle = hWnd.ToString("X8");
dataGridView1.Rows.Add(new string[] { strHandle, strTitle });
}
private void dataGridView1_Click(object sender, EventArgs e)
{
var dgv = (DataGridView)sender;
if (dgv.SelectedRows.Count == 0)
return;
// Get the value of the first cell of the selected row
var value = dgv.SelectedRows[0].Cells[0].Value;
if (value == null)
return;
// Convert the value to IntPtr
var strValue = value.ToString();
var intValue = int.Parse(strValue, System.Globalization.NumberStyles.HexNumber);
var windowHandle = new IntPtr(intValue);
// Do what you want with the window handle
}
Of course, you can also just use EnumChildWindows
to get all "ALT+TAB windows", as long as the callback function has all the necessary filters to filter the different windows.
EnumChildWindows
but then move on to asking how Alt+Tab filters its list of windows. Clearly, the Alt+Tab list doesn't include child windows. So... don't callEnumChildWindows
. – Photozincography