I'm making an application where I interact with each running application. Right now, I need a way of getting the window's z-order. For instance, if Firefox and notepad are running, I need to know which one is in front.
Any ideas? Besides doing this for each application's main window I also need to do it for its child and sister windows (windows belonging to the same process).
Z-order is an ordering of overlapping two-dimensional objects, such as windows in a stacking window manager, shapes in a vector graphics editor, or objects in a 3D application. One of the features of a typical GUI is that windows may overlap, so that one window hides part or all of another.
A child window, owned by a parent form, is not a top-level form, because it has a parent. But it can be on top in the Z order, and can be modal or modeless depending on how it is displayed, with either ShowDiaglog() or Show() respectively.
You can use the GetTopWindow function to search all child windows of a parent window and return a handle to the child window that is highest in z-order. The GetNextWindow function retrieves a handle to the next or previous window in 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
Nice and terse:
int GetZOrder(IntPtr hWnd) { var z = 0; for (var h = hWnd; h != IntPtr.Zero; h = GetWindow(h, GW.HWNDPREV)) z++; return z; }
If you need more reliability:
/// <summary> /// 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. /// </summary> 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; }
(According to the Remarks section on GetWindow
, EnumChildWindows
is safer than calling GetWindow
in a loop because your GetWindow
loop is not atomic to outside changes. According to the Parameters section for EnumChildWindows
, calling with a null parent is equivalent to EnumWindows
.)
Then instead of a separate call to EnumWindows
for each window, which would also be not be atomic and safe from concurrent changes, you send each window you want to compare in a params array so their z-orders can all be retrieved at the same time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With