[Solved] How to handle messages from multiple windows


There are several problems with your code:

  1. ProcessThread() is declared all wrong for CreateThread(), and the compiler would normally scream at you for that, but you are using an erroneous type-cast to quiet the compiler instead of fixing the error. As such, ProcessThread() will not be able to receive the vector correctly at runtime. The ProcessThread() would need to look more like this instead:

    DWORD WINAPI ProcessThread(LPVOID lpParam)
    {
        std::vector<HWND> *Windows = static_cast<std::vector<HWND>*>(lpParam);
        ...
        return 0;
    }
    
    ...
    
    HANDLE hThread = CreateThread(..., &ProcessThread, &Windows, ...);
    
  2. your thread’s message loop is all wrong. Call GetMessage() ONCE per loop iteration, and do not specify any filtering HWND at all (see The dangers of filtering window messages). It will pull the next available message from the message queue, which you can then pass to DispatchMessage() to send the message along to the appropriate WndProc for further processing.

    DWORD WINAPI ProcessThread(LPVOID lpParam)
    {
        std::vector<HWND> *Windows = static_cast<std::vector<HWND>*>(lpParam);
        MSG Msg;
    
        while (GetMessageW(&Msg, 0, 0, 0) > 0)
        {
            TranslateMessage(&Msg);
            DispatchMessageW(&Msg);
        }
    
        return 0;
    }
    
  3. You are creating a worker thread just to wait for it to terminate, without doing anything else in parallel. That makes the worker thread completely useless. You need to get rid of that thread, especially given that…

  4. … you are running your message loop in a separate thread than the one that creates the windows. You can’t do that at all! A window has thread affinity. (Get|Peek)Message() receives messages only for windows associated with the calling thread, so only the thread that creates a window can receive messages for that window.

You are over-thinking your code design. You can greatly simplify it to this:

std::vector<HWND> Windows = { lpScreen.m_WindowHandle, lpPopup.m_WindowHandle };
MSG Msg;

while (GetMessageW(&Msg, 0, 0, 0) > 0)
{
    TranslateMessage(&Msg);
    DispatchMessageW(&Msg);
}

If lpScreen.m_WindowHandle and lpPopup.m_WindowHandle are the only windows available in the calling thread, then you don’t even need the vector at all!

However, if you are interested in processing messages only for specific windows, this does present an issue. The code above will receive messages for ALL windows in the calling thread. If that is not what you want, then you COULD (but shouldn’t!) filter for specific windows in the vector, eg:

std::vector<HWND> Windows = { lpScreen.m_WindowHandle, lpPopup.m_WindowHandle };
MSG Msg;

for(auto h : Windows)
{
    while (PeekMessageW(&Msg, h, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&Msg);
        DispatchMessageW(&Msg);
    }
}

But that can lead to message starvation for other windows, if you are not careful.

Otherwise, you would just have to use a separate thread to CREATE AND PROCESS just the windows you are interested in.

solved How to handle messages from multiple windows