Получить все дескрипторы окна для процесса - PullRequest
7 голосов
/ 11 июня 2010

Используя Microsoft Spy ++, я вижу, что следующие окна принадлежат процессу:

Обрабатывать дескрипторы окна XYZ, отображаемые в виде дерева, как Spy ++ дает мне:

A
  B
  C
     D
E
F
  G
  H
  I
  J
     K

Я могу получить процесс, и свойство MainWindowHandle указывает на дескриптор для окна F. Если я перечислю дочерние окна, используя, я могу получить список дескрипторов окон для G через K, но я не могу понять, как найти дескрипторы окон от A до D. Как я могу перечислить окна, которые не являются потомками дескриптора, указанного в MainWindowHandle объекта Process?

Для перечисления я использую вызов win32:

[System.Runtime.InteropServices.DllImport(strUSER32DLL)]
            public static extern int EnumChildWindows(IntPtr hWnd, WindowCallBack pEnumWindowCallback, int iLParam);

Ответы [ 3 ]

10 голосов
/ 11 июня 2010

Передайте IntPtr.Zero как hWnd, чтобы получить каждый дескриптор корневого окна в системе.

Затем можно проверить процесс владельца окна, вызвав GetWindowThreadProcessId.

7 голосов
/ 16 марта 2014

Для всех, кто все еще задается вопросом, вот ответ:

List<IntPtr> GetRootWindowsOfProcess(int pid)
{
    List<IntPtr> rootWindows = GetChildWindows(IntPtr.Zero);
    List<IntPtr> dsProcRootWindows = new List<IntPtr>();
    foreach (IntPtr hWnd in rootWindows)
    {
        uint lpdwProcessId;
        WindowsInterop.User32.GetWindowThreadProcessId(hWnd, out lpdwProcessId);
        if (lpdwProcessId == pid)
            dsProcRootWindows.Add(hWnd);
    }
    return dsProcRootWindows;
}

public static List<IntPtr> GetChildWindows(IntPtr parent)
{
    List<IntPtr> result = new List<IntPtr>();
    GCHandle listHandle = GCHandle.Alloc(result);
    try
    {
        WindowsInterop.Win32Callback childProc = new WindowsInterop.Win32Callback(EnumWindow);
        WindowsInterop.User32.EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
    }
    finally
    {
        if (listHandle.IsAllocated)
            listHandle.Free();
    }
    return result;
}

private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
    GCHandle gch = GCHandle.FromIntPtr(pointer);
    List<IntPtr> list = gch.Target as List<IntPtr>;
    if (list == null)
    {
        throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
    }
    list.Add(handle);
    //  You can modify this to check to see if you want to cancel the operation, then return a null here
    return true;
}

для WindowsInterop:

public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

для WindowsInterop.User32:

[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

Теперь можно просто получить каждое корневое окно с помощью GetRootWindowsOfProcess, а их потомков - с помощью GetChildWindows.

7 голосов
/ 11 июня 2010

Вы можете использовать EnumWindows, чтобы получить каждое окно верхнего уровня, а затем отфильтровать результаты на основе GetWindowThreadProcessId.

...