4
votes

I'm looking for a window that its class name is "CLIPBRDWNDCLASS" (it can be found in office apps and other applications).

If I use FindWindow or FindWindowEx I find the first HWND that has this class, but I want all the windows with that class, so I decided to use recursive EnumChildWindows to enumerate all windows and find the window I want:

//-------------------------------------------------------------------------------
BOOL CALLBACK enum_wnd_proc(HWND h, LPARAM lp)
{
    char cls[1024] = {0};
    ::GetClassNameA(h, cls, 1024);

    if(std::string(cls) == "CLIPBRDWNDCLASS")
    {
        // match!
    }

    ::EnumChildWindows(h, enum_wnd_proc, NULL);

    return TRUE;
}
//-------------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
    ::EnumWindows(enum_wnd_proc, NULL); 
    return 0;
}
//-------------------------------------------------------------------------------

The this is that this window does not return by the EnumWindows, only by FindWindow.

Does anyone can tell why it doesn't work ???

2
First, EnumChildWindows() is already recursive and you don't need to call it again within the callback function. Second, try printing the class names of all the windows you come across and see if it gives you a hint. - Asaf
@Asaf - Thanks about EnumChildWindows() being recursive, I didn't know that. I thought its only the direct children. I've tried printing all the names, but it didn't get me anywhere.... It looks like this window simply ignores the EnumChildWindows(), but can be found using FindWindowEx(). - TCS
yes, they named it badly. Are you trying to use it in the same process as the windows themselves? - Asaf
@Asaf - No... I don't think it matters... - TCS

2 Answers

9
votes

The reason EnumWindows doesn't work is that the window you are looking for is a message only window.

FindWindowEx can find them in two cases:

  1. If both hwndParent and hwndChildAfter are NULL.
  2. If you specify 'HWND_MESSAGE' as your parent window.

This code will find all the relevant windows for you (a modified version of a solution from here):

HWND hWindow = FindWindowExA(HWND_MESSAGE, NULL, "CLIPBRDWNDCLASS", NULL);
while (hWindow )
{
    // Do something here with window...

    // Find next window
    hWindow = FindWindowExA(HWND_MESSAGE, hWindow , "CLIPBRDWNDCLASS", NULL);
}

Also note that unlike what's written in the above link, GetParent() for message only windows does not return HWND_MESSAGE (at least not for my tests).

4
votes

My old easy way to ENUMERATE all message-only windows:

EnumChildWindows(GetAncestor(FindWindowEx(HWND_MESSAGE,0,0,0),GA_PARENT),addr EnumChildProc,0)

// GetAncestor(FindWindowEx(HWND_MESSAGE,0,0,0),GA_PARENT) = "GetMessageWindow" (class "Message")

// GetAncestor(FindWindowEx(HWND_DESKTOP,0,0,0),GA_PARENT) = GetDesktopWindow (class "#32769")