Как я могу получить дочерние окна окна, учитывая его HWND? - PullRequest
26 голосов
/ 01 сентября 2009

У меня есть ручка для данного окна. Как я могу перечислить его дочерние окна?

Ответы [ 5 ]

22 голосов
/ 21 января 2015

Здесь у вас есть рабочий раствор:

public class WindowHandleInfo
{
    private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);

    [DllImport("user32")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);

    private IntPtr _MainHandle;

    public WindowHandleInfo(IntPtr handle)
    {
        this._MainHandle = handle;
    }

    public List<IntPtr> GetAllChildHandles()
    {
        List<IntPtr> childHandles = new List<IntPtr>();

        GCHandle gcChildhandlesList = GCHandle.Alloc(childHandles);
        IntPtr pointerChildHandlesList = GCHandle.ToIntPtr(gcChildhandlesList);

        try
        {
            EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
            EnumChildWindows(this._MainHandle, childProc, pointerChildHandlesList);
        }
        finally
        {
            gcChildhandlesList.Free();
        }

        return childHandles;
    }

    private bool EnumWindow(IntPtr hWnd, IntPtr lParam)
    {
        GCHandle gcChildhandlesList = GCHandle.FromIntPtr(lParam);

        if (gcChildhandlesList == null || gcChildhandlesList.Target == null)
        {
            return false;
        }

        List<IntPtr> childHandles = gcChildhandlesList.Target as List<IntPtr>;
        childHandles.Add(hWnd);

        return true;
    }
}

Как его употреблять:

class Program
{
    [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
    public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    static void Main(string[] args)
    {
        Process[] anotherApps = Process.GetProcessesByName("AnotherApp");
        if (anotherApps.Length == 0) return;
        if (anotherApps[0] != null)
        {
            var allChildWindows = new WindowHandleInfo(anotherApps[0].MainWindowHandle).GetAllChildHandles();
        }
    }
}
11 голосов
/ 01 сентября 2009

Использование:

internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);

[DllImport("user32.dll")]
internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);

вы получите обратные вызовы для функции, которую вы передаете.

7 голосов
/ 01 сентября 2009

Я нашел лучшее решение для Управляемый WindowsAPI . У него был элемент управления CrossHair, который можно использовать для выбора окна (не является частью вопроса), и метод AllChildWindows, чтобы получить все дочерние окна, которые, вероятно, заключают в себе функцию EnumChildWindows. Лучше не изобретать велосипед.

6 голосов
/ 01 сентября 2009

Используйте EnumChildWindows, с p / invoke. Вот интересная ссылка о его поведении: https://blogs.msdn.microsoft.com/oldnewthing/20070116-04/?p=28393

Если вы не знаете дескриптор окна, а только его заголовок, вам нужно использовать EnumWindows. http://pinvoke.net/default.aspx/user32/EnumWindows.html

3 голосов
/ 01 сентября 2009

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

foreach (Process process in Process.GetProcesses())
{
   if (process.MainWindowTitle == "Title to find")
   {
      IntPtr handle = process.MainWindowHandle;

      // Use EnumChildWindows on handle ...
   }
}
...