Pregunta

Estoy creando una aplicación en la que 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.

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

¿Fue útil?

Solución

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

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

Otros consejos

Agradable y conciso:

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:

/// <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;
}

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

Luego, en lugar de una llamada separada a EnumWindows para cada ventana, que tampoco sería atómica y estaría a salvo de los cambios concurrentes, envía cada ventana que desea comparar en una matriz de parámetros para que su z -los pedidos se pueden recuperar todos 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 de C #: La función devuelve el índice zIndex entre los hermanos del HWND dado, comenzando en 0 para la orden z más baja.

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;
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top