I'm developing a small utility application that needs to detect whether another one has one of its MDI child windows open (it's an off-the-shelf Win32 business application over which I have neither source code nor control). From my app, I would like to be able to poll or detect when a particular MDI Child window is open.
In .Net, it's easy to iterate over running processes, but I haven't found an easy way to iterate through the (sub)windows and controls of a given Win32 process from .Net.
Any ideas?
Update
Thanks for the answers they got me on the right path.
I found an article with a test project that uses both EnumWindows
and EnumChidWindows
and other API calls to get extended information on controls.
-
You can use P/Invoke to access EnumWindows and EnumChidWindows to itereate through the subwindows/controls of any window.
-
You must use native Win32 API.
[DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i); /// <summary> /// Returns a list of child windows /// </summary> /// <param name="parent">Parent of the windows to return</param> /// <returns>List of child windows</returns> public static List<IntPtr> GetChildWindows(IntPtr parent) { List<IntPtr> result = new List<IntPtr>(); GCHandle listHandle = GCHandle.Alloc(result); try { EnumWindowProc childProc = new EnumWindowProc(EnumWindow); EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); } finally { if (listHandle.IsAllocated) listHandle.Free(); } return result; } /// <summary> /// Callback method to be used when enumerating windows. /// </summary> /// <param name="handle">Handle of the next window</param> /// <param name="pointer">Pointer to a GCHandle that holds a reference to the list to fill</param> /// <returns>True to continue the enumeration, false to bail</returns> 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; } /// <summary> /// Delegate for the EnumChildWindows method /// </summary> /// <param name="hWnd">Window handle</param> /// <param name="parameter">Caller-defined variable; we use it for a pointer to our list</param> /// <returns>True to continue enumerating, false to bail.</returns> public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
0 comments:
Post a Comment