Search code examples
c#windowswindows-10system.diagnostics

Retrieve order of open windows as ordered in the Alt-Tab list?


This is the entire code of my C# application, with a simple goal. I want to retrieve the open windows on the system, ordered by how they were recently opened, just like in the Alt-Tab list. The Alt-Tab list lists programs as they were last opened, so that pressing Alt-Tab and releasing only once will take you back to the last window you had opened. This code is for Windows 10. The code below does get the information I need, just not in the right order. Where should I look for the information I need?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace GetOpenWindowName
{
    class Program
    {
        static void Main(string[] args)
        {
            Process[] processlist = Process.GetProcesses();

            foreach (Process process in processlist)
            {
                if (!String.IsNullOrEmpty(process.MainWindowTitle))
                {
                    Console.WriteLine("Process: {0} ID: {1} Window title: {2}", process.ProcessName, process.Id, process.MainWindowTitle);
                }
            }

            Console.ReadLine();
        }
    }
}

Solution

  • So, this is the best that I was able to do, with the help of @PaulF, @stuartd, and @IInspectible.

    The order of the windows in the Alt-Tab list is roughly the z-order of the windows. @IInspectible informs us that a window set to topmost will break this, but for the most part, z-order can be respected. So, we need to get the z-order of open windows.

    First, we need to bring in the external function GetWindow, using these two lines:

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr GetWindow(IntPtr hWnd, int nIndex);
    

    Once that function exists, we can create this function to get the z-order:

    public static int GetZOrder(Process p)
    {
        IntPtr hWnd = p.MainWindowHandle;
        var z = 0;
        // 3 is GetWindowType.GW_HWNDPREV
        for (var h = hWnd; h != IntPtr.Zero; h = GetWindow(h, 3)) z++;
        return z;
    }
    

    Key point: the three in the call to the GetWindow function is a flag:

    /// <summary>
    /// The retrieved handle identifies the window above the specified window in the Z order.
    /// <para />
    /// If the specified window is a topmost window, the handle identifies a topmost window.
    /// If the specified window is a top-level window, the handle identifies a top-level window.
    /// If the specified window is a child window, the handle identifies a sibling window.
    /// </summary>
    GW_HWNDPREV = 3,
    

    These are the building blocks to finding the z-order of the windows from a process list, which is (for the most part) what the Alt-Tab order is.