代码之家  ›  专栏  ›  技术社区  ›  Yuriy Faktorovich

我如何获得给定HWND的窗户的子窗户?

  •  44
  • Yuriy Faktorovich  · 技术社区  · 16 年前

    5 回复  |  直到 16 年前
        1
  •  21
  •   Caffé    11 年前

    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();
            }
        }
    }
    
        2
  •  11
  •   Grzenio    16 年前

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

        3
  •  7
  •   Yuriy Faktorovich    16 年前

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

        4
  •  6
  •   Markus Jarderot    10 年前

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

    http://pinvoke.net/default.aspx/user32/EnumWindows.html

        5
  •  3
  •   Special Touch    16 年前

    这是EnumWindows的托管替代方案,但您仍需要使用 EnumChildWindows

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