0

I'm trying to get windows' names when they are created and went with the route of using accessibility hooks. However, it seems that I'm getting invalid window handles from the WINEVENTPROC struct. I'm requesting EVENT_OBJECT_SHOW in my SetWinEventHook function and checking if the idObject is OBJID_WINDOW, but I still seem to get invalid handles when using GetWindowTextW and GetWindowTextLengthW. I also already checked to see if it's a valid window handle using IsWindow but still got the same result. One instance when this happens is when hovering over the icon of an opened window in the taskbar.

My hook function


void CALLBACK WinEventProc(
    HWINEVENTHOOK hWinEventHook,
    DWORD event,
    HWND hwnd,
    LONG idObject,
    LONG idChild,
    DWORD dwEventThread,
    DWORD dwmsEventTime
)
{
    if (hwnd && idObject == OBJID_WINDOW && idChild == CHILDID_SELF) {
        switch (event) {
        case EVENT_OBJECT_SHOW:
            int l = GetWindowTextLengthW(hwnd);
            auto* txt = new wchar_t[l + 1];
            if (!GetWindowTextW(hwnd, txt, l + 1)) {
                std::cout << "error " << GetLastError() << "\n";
            } else {
                auto text = std::wstring(txt);
                std::wcout << text << "\n";
            }
            break;
        }
    }
}

This is my hook creation

HWINEVENTHOOK hWinEventHook = SetWinEventHook(
  EVENT_OBJECT_SHOW, EVENT_OBJECT_SHOW,
  NULL, WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS
);

I believe this is because not all handles provided may be valid window handles, if that is the case, how can I ignore these window handles?

John Boyer
  • 27
  • 3
  • *although GetWindowTextLengthW works fine for that same handle* - it can not *work fine* if *hwnd* not valid. `GetLastError()` is what ? and call it just after api call not like in your code – RbMm Mar 10 '21 at 15:17
  • Sorry, you're correct. I checked again and GetWindowTextLengthW also does not work. – John Boyer Mar 10 '21 at 15:42
  • are you get error (what is `GetLastError` return) or simply 0 text length ? window can have no text/caption – RbMm Mar 10 '21 at 15:51
  • How did you determine, that those window handles were invalid? Did you call [IsWindow](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindow)? Also, as with every C++ developer, you are calling `GetLastError` too late. You need to call it **immediately** when the documentation tells you that it will return a meaningful value. Do not put **any** code in between. Certainly not a monster like an I/O stream insertion operator. – IInspectable Mar 10 '21 at 15:56
  • Besides, if you really want to monitor window creation (as the question title explains), you should probably register for [EVENT_OBJECT_CREATE](https://learn.microsoft.com/en-us/windows/win32/winauto/event-constants) events. – IInspectable Mar 10 '21 at 15:59
  • After moving the call to `GetLastError` to before the I/O, it seems to succeed (error code of 0). I decided to go with `EVENT_OBJECT_SHOW` rather than `_CREATE` because there was a lot of window activity that I didn't need. The length of the windows' names are 0 so I assume it's safe to ignore these since I'm looking for specific windows. – John Boyer Mar 10 '21 at 16:16
  • 1
    The window text is an unreliable metric for identifying windows. It's subject to change over time, frequently changes across different UI languages, and very frequently doesn't represent what you see on screen ([The secret life of GetWindowText](https://devblogs.microsoft.com/oldnewthing/20030821-00/?p=42833)). This is starting to sound like the [XY Problem](https://xyproblem.info). – IInspectable Mar 10 '21 at 16:35
  • If you want to find a specific window, you can try to use `EnumWindows`. Refer to this thread:[C++ Win API - FindWindow() or EnumWindows() to retrieve specific windows](https://stackoverflow.com/a/66257200/13566062) – Zeus Mar 11 '21 at 05:50

0 Answers0