【问题标题】:How can I get the child windows of a window given its HWND?在给定 HWND 的情况下,如何获取窗口的子窗口?
【发布时间】:2010-11-24 16:36:00
【问题描述】:

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

【问题讨论】:

  • 一般来说。我可以获取要从中枚举的窗口的 HWND。
  • 非常好 - 我已经更新了你的问题以明确这一点。
  • 假设您了解 spy++。处理这些东西的有用工具。
  • 我愿意,如果你喜欢 spy++,你可能想试试 Winspector spy。我发现它更容易使用更多选项。

标签: c# windows winapi children


【解决方案1】:

Here你有一个可行的解决方案:

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

【讨论】:

  • 如何获取 user32.dll ??
  • @jai 这是一个 Windows 库,它已经存在并已在您的计算机中注册。该代码应该可以在不需要额外引用的情况下工作。
  • 感谢@caffe ....但实际上如果我使用 user32.dll ,应用程序要求某种权限...我无法运行应用程序...我该如何解决那...
  • 很确定 GCHandle.FromIntPtr 不能返回 null。
  • pinvoke.net 是参考使用 win API 的好地方。
【解决方案2】:

使用:

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

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

你会得到你传入的函数的回调。

【讨论】:

    【解决方案3】:

    我发现最好的解决方案是Managed WindowsAPI。它有一个 CrossHair 控件,可以用来选择一个窗口(不是问题的一部分),还有一个 AllChildWindows 方法来获取所有可能包含 EnumChildWindows 函数的子窗口。最好不要重新发明轮子。

    【讨论】:

      【解决方案4】:

      将 EnumChildWindows 与 p/invoke 一起使用。这是一个关于它的一些行为的有趣链接:https://blogs.msdn.microsoft.com/oldnewthing/20070116-04/?p=28393

      如果您不知道窗口的句柄,而只知道它的标题,则需要使用 EnumWindows。 http://pinvoke.net/default.aspx/user32/EnumWindows.html

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

        • 我正在尝试执行此操作,但该进程没有主窗口。
        • Epu,如果没有主窗口则进程将没有窗口句柄可获取(即Process.MainWindowHandle == IntPtr.Zero)。
        猜你喜欢
        • 2020-02-03
        • 2013-07-13
        • 1970-01-01
        • 2013-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-28
        相关资源
        最近更新 更多