C# 如何在给定窗口的HWND的情况下获取其子窗口?

C# 如何在给定窗口的HWND的情况下获取其子窗口?,c#,windows,winapi,children,C#,Windows,Winapi,Children,我有一个给定窗口的句柄。如何枚举其子窗口?使用: internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam); [DllImport("user32.dll")] internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam); 您将收到传入函数的回调。使用EnumChildWindows,并使用p/

我有一个给定窗口的句柄。如何枚举其子窗口?

使用:

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

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

您将收到传入函数的回调。

使用EnumChildWindows,并使用p/invoke。这里有一个关于它的一些行为的有趣链接:


如果您不知道窗口的句柄,但只知道它的标题,则需要使用EnumWindows

这里是EnumWindows的托管替代方案,但您仍需要使用来查找子窗口的句柄

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

      // Use EnumChildWindows on handle ...
   }
}

我找到了最好的解决办法。它有一个十字线控件,可以用来选择一个窗口(不是问题的一部分),还有一个AllChildWindows方法来获取所有子窗口,这可能会包装EnumChildWindows函数。最好不要重新发明轮子。

您有一个可行的解决方案:

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

一般来说我可以得到我想列举的窗口的HWND。非常好-我已经更新了你的问题来说明这一点。假设你知道spy++。这是一个非常有用的工具,如果你喜欢spy++,你可以试试Winspector spy。我发现使用更多选项更容易。我正在尝试这样做,但进程没有主窗口。Epu,如果没有主窗口,则进程将没有要获取的窗口句柄(即process.MainWindowHandle==IntPtr.Zero)。我如何获取user32.dll???@jai它是一个Windows库,它已存在并在您的计算机中注册。该代码不需要额外的引用就可以工作。谢谢@caffe。。。。但实际上,如果我使用user32.dll,应用程序请求某种权限…我无法运行应用程序…我如何解决这个问题…非常确定
GCHandle.FromIntPtr
不能返回null。是一个很好的参考使用WinAPI的地方。
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();
        }
    }
}