実行中の各アプリケーションと対話するアプリケーションを作成しています。今、ウィンドウの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
呼び出しよりも安全です。 のパラメーター セクションによると、null の親での呼び出しは と同等です。)GetWindow
GetWindow
EnumChildWindows
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);