簡體   English   中英

如何在Windows中獲取z順序?

[英]How to get the z-order in windows?

我正在制作一個應用程序,在其中與每個正在運行的應用程序進行交互。 現在,我需要一種獲取窗口 z 順序的方法。 例如,如果 Firefox 和記事本正在運行,我需要知道哪個在前面。

有任何想法嗎? 除了為每個應用程序的主窗口執行此操作外,我還需要為其子窗口和姐妹窗口(屬於同一進程的窗口)執行此操作。

您可以使用 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

漂亮而簡潔:

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

(根據GetWindow的備注部分, EnumChildWindows比在循環中調用GetWindow更安全,因為您的GetWindow循環不是外部更改的原子。根據EnumChildWindows的參數部分,使用 null 父級調用等效於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;
        }
    }
}
            // 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);

對於獲取 Z-Order 實現此函數(通過使用GetWindow Windows 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;
}

返回值是一個從零開始的索引 返回 -1 表示無效的 hWnd。

方法是通過窗戶到頂部。 爬升的總數是 Z-Order 的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM