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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/825595/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:09:15  来源:igfitidea点击:

How to get the z-order in windows?

c#.netwindowsz-order

提问by user361526

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.

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

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).

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

采纳答案by NineBerry

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 函数搜索父窗口的所有子窗口,并返回 z 顺序最高的子窗口的句柄。GetNextWindow 函数按 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

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

回答by MightyZot

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

回答by jnm2

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, EnumChildWindowsis safer than calling GetWindowin a loop because your GetWindowloop is not atomic to outside changes. According to the Parameters section for EnumChildWindows, calling with a null parent is equivalent to EnumWindows.)

(根据 的备注部分GetWindowEnumChildWindowsGetWindow在循环中调用更安全,因为您的GetWindow循环对于外部更改不是原子的。根据 的参数部分EnumChildWindows,使用 null 父级调用等效于EnumWindows。)

Then instead of a separate call to EnumWindowsfor 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.

然后,不是EnumWindows对每个窗口单独调用,这对于并发更改也不是原子和安全的,而是将要比较的每个窗口发送到 params 数组中,以便可以同时检索它们的 z 顺序。

回答by Kino101

Here is my C# solution: The function returns the zIndex among the siblings of the given HWND, starting at 0 for the lowest zOrder.

这是我的 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;
        }
    }
}

回答by Sergio Cabral

For get Z-Order implement this function (by using GetWindowWindows API function)

对于获取 Z-Order 实现此功能(通过使用GetWindowWindows API 功能)

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

The return value is a zero-based index. Returning -1 indicates an invalid hWnd.

返回值是一个从零开始的索引。返回 -1 表示无效的 hWnd。

The approach is to go up through the windows to the top. The total number of climbs is the value of the Z-Order.

方法是通过窗户到顶部。爬升的总数就是 Z-Order 的值。