5

Suppose I've this Window hierarchy for one of the processes:

Main Window               (class name: XYZ_Widget_1)
`- Child Window           (class name: XYZ_Widget_0)
  `- Child-Child Window    (class name: XYZ_Renderer)

How do I find the HWND of the Child-Child Window?

I tried using FindWindow Win32 API function on XYZ_Renderer class but the FindWindow function doesn't find child windows.

Then I tried using FindWindow to find Main Window, which succeeded, but after that using FindWindowEx can only find Child Window as Child-Child Window is not a child of Main Window.

I guess I could go one layer deeper and call FindWindowEx on the Child Window once it's found.

But before I do that I figured maybe there is an easy way to find Child-Child Window?

bodacydo
  • 75,521
  • 93
  • 229
  • 319

2 Answers2

14

You have to call FindWindowEx() for each child level that you want to go down, specifying the HWND found in the previous level as the parent, eg:

HWND hWnd = FindWindow("XYZ_Widget_1", NULL);
if (hWnd != NULL)
{
    hWnd = FindWindowEx(hWnd, NULL, "XYZ_Widget_0", NULL);
    if (hWnd != NULL)
    {
        hWnd = FindWindowEx(hWnd, NULL, "XYZ_Renderer", NULL);
        // and so on... 
    }
}

There is no simplier way to do it. To simplify your code, you could write your own function that accepts a path of class/window names as input, looping through it calling FindWindow/Ex() for each leg as needed.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
6

Call EnumChildWindows passing the parent window as hwndParent. Your window is the window with class name equal to XYZ_Renderer.

The documentation states that:

If a child window has created child windows of its own, EnumChildWindows enumerates those windows as well.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • But I don't have the `hwndParent` if I want to find `XYZ_Renderer` from the beginning. I first have to find `XYZ_Widget_0` (`Child Window`) window. But before I can find it, I've to find `XYZ_Widget_1` (`Main Window`). – bodacydo Oct 05 '12 at 13:27
  • You just need to obtain the top level window. FindWindow can do that. Or EnumWindows. – David Heffernan Oct 05 '12 at 13:32
  • I did obtain the top level window. If I use `EnumChildWindows` on the top level window it does not find the `XYZ_Renderer` because `XYZ_Renderer` is not a child of the top level window. It's a child of `XYZ_Widget_0`... (See my diagram) – bodacydo Oct 05 '12 at 14:45
  • I'm trying the answer below, where I've to use FindWIndowEx twice. – bodacydo Oct 05 '12 at 14:46
  • I think we're not on the same page. I'm sorry, English is not my native language. – bodacydo Oct 05 '12 at 14:58
  • I can easily find the top level window by `FindWindow`. However calling `EnumChildWindows` enumerats only direct child windows of the top level window. It doesn't find the child-child windows. Does that make sense? – bodacydo Oct 05 '12 at 14:59
  • OK, I missed that comment. `EnumChildWindows` walks the children recursively. It will find all children, all their children and so on. I repeat, `EnumChildWindows` finds all children, and not just direct children. Raymond talked about this: http://blogs.msdn.com/b/oldnewthing/archive/2007/01/16/1478717.aspx – David Heffernan Oct 05 '12 at 15:00
  • Oh it does? In my tests it looked like it only walked one layer of child windowses. Let me re-test. Thanks for your patience. – bodacydo Oct 05 '12 at 15:01
  • I somehow can't get the EnumChildWindows enumerate child windows recursively. It only returns the first level of child windows on my machine. I implemented @RemyLebeau solution below and it woks really well. Thanks for your time and patience. – bodacydo Oct 05 '12 at 20:31
  • You must be doing something wrong. The API really does work as advertised. But never mind. You have a solution. – David Heffernan Oct 05 '12 at 20:39
  • 1
    I can verify that `EnumChildWindows()` does work as advertised, at least on Win7. It really does enumerate immediate child windows and descendant windows. I created a VCL form with a bunch of nested controls on it, then called `EnumChildWindows()` only once with the Form's `Handle` as the parent window. It did recurse through all of the nested controls. – Remy Lebeau Oct 05 '12 at 21:08
  • Windows 10 and i can see that `EnumChildWindows` only returns top level children. I need to add custom recursion into it to make it return all the children. This is very strange behaviour from API. – ScienceDiscoverer Jul 22 '23 at 03:53
  • @ScienceDiscoverer that's incorrect – David Heffernan Jul 22 '23 at 05:40