¿Cómo obtener el orden z en Windows?

Estoy haciendo una aplicación donde interactúo con cada aplicación en ejecución. En este momento, necesito una forma de obtener el orden Z de la ventana. Por ejemplo, si Firefox y el Bloc de notas se están ejecutando, necesito saber cuál está al frente.

¿Algunas ideas? Además de hacer esto para la ventana principal de cada aplicación, también tengo que hacerlo para sus ventanas secundarias y secundarias (ventanas que pertenecen al mismo proceso).

Puede usar la función GetTopWindow para buscar en todas las ventanas secundarias de una ventana principal y devolver un manejador a la ventana secundaria que esté más alta en orden z. La función GetNextWindow recupera un manejador de la ventana siguiente o anterior en z-order.

GetTopWindow: http://msdn.microsoft.com/en-us/library/ms633514(VS.85).aspx
GetNextWindow: http://msdn.microsoft.com/en-us/library/ms633509(VS.85).aspx

Agradable y concisa

 int GetZOrder(IntPtr hWnd) { var z = 0; for (var h = hWnd; h != IntPtr.Zero; h = GetWindow(h, GW.HWNDPREV)) z++; return z; } 

Si necesita más confiabilidad:

 ///  /// Gets the z-order for one or more windows atomically with respect to each other. In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1. ///  int[] GetZOrder(params IntPtr[] hWnds) { var z = new int[hWnds.Length]; for (var i = 0; i < hWnds.Length; i++) z[i] = -1; var index = 0; var numRemaining = hWnds.Length; EnumWindows((wnd, param) => { var searchIndex = Array.IndexOf(hWnds, wnd); if (searchIndex != -1) { z[searchIndex] = index; numRemaining--; if (numRemaining == 0) return false; } index++; return true; }, IntPtr.Zero); return z; } 

(De acuerdo con la sección Comentarios en GetWindow , EnumChildWindows es más seguro que llamar GetWindow en un bucle porque su bucle GetWindow no es atómico a cambios externos. De acuerdo con la sección Parámetros de EnumChildWindows , llamar con un elemento primario nulo es equivalente a EnumWindows ).

Luego, en lugar de una llamada separada a EnumWindows para cada ventana, que tampoco sería atómica ni segura frente a cambios concurrentes, envíe cada ventana que desee comparar en una matriz params para que sus órdenes z puedan recuperarse todas al mismo tiempo. .

  // Find z-order for window. Process[] procs = Process.GetProcessesByName("notepad"); Process top = null; int topz = int.MaxValue; foreach (Process p in procs) { IntPtr handle = p.MainWindowHandle; int z = 0; do { z++; handle = GetWindow(handle, 3); } while(handle != IntPtr.Zero); if (z < topz) { top = p; topz = z; } } if(top != null) Debug.WriteLine(top.MainWindowTitle); 

Aquí está mi solución C #: la función devuelve el índice z entre los hermanos del HWND dado, comenzando en 0 para el zOrder más bajo.

 using System; using System.Runtime.InteropServices; namespace Win32 { public static class HwndHelper { [DllImport("user32.dll")] private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); public static bool GetWindowZOrder(IntPtr hwnd, out int zOrder) { const uint GW_HWNDPREV = 3; const uint GW_HWNDLAST = 1; var lowestHwnd = GetWindow(hwnd, GW_HWNDLAST); var z = 0; var hwndTmp = lowestHwnd; while (hwndTmp != IntPtr.Zero) { if (hwnd == hwndTmp) { zOrder = z; return true; } hwndTmp = GetWindow(hwndTmp, GW_HWNDPREV); z++; } zOrder = int.MinValue; return false; } } }