Windows에서 Z-Order를 얻는 방법?
문제
각 실행중인 응용 프로그램과 상호 작용하는 응용 프로그램을 만들고 있습니다. 지금은 창의 zorord를 얻는 방법이 필요합니다. 예를 들어, Firefox와 Notepad가 실행중인 경우 어느쪽에 있는지 알아야합니다.
어떤 아이디어? 각 응용 프로그램의 기본 창에 대해이 작업을 수행하는 것 외에도 자녀와 자매 창 (동일한 프로세스에 속하는 창)을 위해 수행해야합니다.
해결책
getTopWindow 함수를 사용하여 부모 창의 모든 자식 창을 검색하고 Z-Order에서 가장 높은 어린이 창으로 핸들을 반환 할 수 있습니다. getNextWindow 함수는 Z-Order의 다음 또는 이전 창으로의 핸들을 검색합니다.
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
원자력이없고 동시 변경으로부터 안전하지 않은 각 창에 대해 매개 변수 배열에서 비교하려는 각 창을 보내므로 Z-ord를 모두 동시에 검색 할 수 있습니다.
// 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);
내 C# 솔루션은 다음과 같습니다. 함수는 주어진 HWND의 형제 자매들 사이에서 zindex를 반환하여 0에서 가장 낮은 Zorder를 위해 시작합니다.
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;
}
}
}