C# 如何在windows中获取z顺序?

C# 如何在windows中获取z顺序?,c#,.net,windows,z-order,C#,.net,Windows,Z Order,我正在制作一个应用程序,其中我与每个正在运行的应用程序进行交互。现在,我需要一种方法来获取窗口的z顺序。例如,如果Firefox和记事本正在运行,我需要知道哪一个在前面 有什么想法吗?除了对每个应用程序的主窗口执行此操作外,我还需要对其子窗口和姐妹窗口(属于同一进程的窗口)执行此操作。您可以使用GetTopWindow函数搜索父窗口的所有子窗口,并返回z顺序最高的子窗口句柄。GetNextWindow函数按z顺序检索下一个或上一个窗口的句柄 GetTopWindow: GetNextWindow

我正在制作一个应用程序,其中我与每个正在运行的应用程序进行交互。现在,我需要一种方法来获取窗口的z顺序。例如,如果Firefox和记事本正在运行,我需要知道哪一个在前面


有什么想法吗?除了对每个应用程序的主窗口执行此操作外,我还需要对其子窗口和姐妹窗口(属于同一进程的窗口)执行此操作。

您可以使用GetTopWindow函数搜索父窗口的所有子窗口,并返回z顺序最高的子窗口句柄。GetNextWindow函数按z顺序检索下一个或上一个窗口的句柄

GetTopWindow:
GetNextWindow:

//查找窗口的z顺序。
Process[]procs=Process.getProcessByName(“记事本”);
进程top=null;
int topz=int.MaxValue;
foreach(过程中的过程p)
{
IntPtr handle=p.MainWindowHandle;
int z=0;
做
{
z++;
handle=GetWindow(handle,3);
}while(handle!=IntPtr.Zero);
if(z
简洁明了:

int GetZOrder(IntPtr hWnd)
{
    var z = 0;
    for (var h = hWnd; h != IntPtr.Zero; h = GetWindow(h, GW.HWNDPREV)) z++;
    return z;
}
如果您需要更高的可靠性:

/// <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;
}
//
///获取一个或多个窗口相对于彼此的原子顺序。在Windows中,z阶越小越好。如果窗口不是顶层,则z顺序返回为-1。
/// 
int[]GetZOrder(参数IntPtr[]hWnds)
{
var z=新整数[hWnds.Length];
对于(变量i=0;i
{
var searchIndex=Array.IndexOf(hWnds,wnd);
如果(搜索索引!=-1)
{
z[搜索索引]=索引;
numRemaining--;
如果(numRemaining==0)返回false;
}
索引++;
返回true;
},IntPtr.Zero);
返回z;
}
(根据上的备注部分,
EnumChildWindows
比在循环中调用
GetWindow
更安全,因为您的
GetWindow
循环对外部更改不是原子的。根据的参数部分,使用空父项调用相当于
EnumWindows

然后,不是为每个窗口单独调用
EnumWindows
,因为它也不是原子的,不会受到并发更改的影响,而是将要比较的每个窗口发送到一个params数组中,以便可以同时检索它们的z顺序。

下面是我的C#解决方案: 该函数返回给定HWND的同级中的zIndex,对于最低的zOrder,从0开始

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

对于get Z-Order,请实现此函数(使用
GetWindow
windowsapi函数)

返回值是一个基于零的索引。返回-1表示hWnd无效


方法是通过窗户上升到顶部。爬升的总数是Z顺序的值。

并且“桌面”应该能够通过为父窗口指定null来用作父窗口。因此,你可以很容易地获得桌面上的顶级窗口。这是不可靠的
GetNextWindow
只需调用
GetWindow
。来自:“调用GetWindow来执行此任务的应用程序可能会陷入无限循环或引用已销毁窗口的句柄。”在比较两个重叠窗口(例如窗体和任务栏)时不起作用。当窗口位于任务栏上方时,任务栏的z顺序高于显示任务栏位于顶部的窗口,而不是。事实上,我改变了主意@在Erwinus中,顶级窗口以z顺序出现在其他窗口之前,这意味着z顺序数越小,则表示该窗口实际上越高。
EnumWindows
GW_hwndprov
GW_hwndpnext
的工作方式证明了这一点。这里的其他答案是一致的。我不愿意将此计数器用于Windows API。是的,对此方法有一些疑问。无论如何都要使用您的第一个代码(使用getWindow(h,gwhwndprov)),但略有不同。当一个窗口位于另一个窗口的顶部时,您可以测试下部窗口是否在“列表”中。如果为true,则必须检查窗口的边界,以检查它是否确实重叠。
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;
        }
    }
}
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

static int GetWindowZOrder(IntPtr hWnd)
{
    var zOrder = -1;
    while ((hWnd = GetWindow(hWnd, 2 /* GW_HWNDNEXT */)) != IntPtr.Zero) zOrder++;
    return zOrder;
}