Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thoughts on a different way to running a win32 event loop without WndProc?

Whilst messing around with multithreading, callbacks, win32 api functions, and other troublesome troubles, I received an idea event. (hehehe)

What if, instead of defining a global (or static when designing a class) callback function, I instead assigned DefWindowProc for lpfnWndProc when registering the window class, and then ran the whole event loop on a separate thread?

This way I don't have to hack around the this problem when implementing the callback in a class and the main thread's execution continues, freeing you from that god-forsaken while loop, allowing you to do whatever, even open another window (yay!)

The "normal" way:

LRESULT CALLBACK WndProc(...)
{
    ... // process event information
    return DefWindowProc(...);
}

int CALLBACK WinMain(...)
{
    ... // initialize whatever needs initializing :)
    WNDCLASSEX wc;
    ...
    wc.lpfnWndProc = WndProc;
    ... // register the class, create the window, etc...

   MSG msg;
   while(GetMessage(&msg, 0, 0, 0) != 0)
   {
        ... // TranslateMessage(&msg) if you want/need it
        DispatchMessage(&msg); // dispatches the message to WndProc
   }

   return static_cast<int>(msg.wParam);
}

My newfound awesome way:

DWORD WINAPI MyAwesomeEventLoop(void* data) // must be static in a class
{
    ... // do whatever you need with the data
    MSG msg;
    while(GetMessage(&msg, 0, 0, 0) != 0)
    {
        ... // TranslateMessage(&msg) if you want/need it
        ... // process event information
            // call PostQuitMessage(0) to leave the loop
    }

    return static_cast<DWORD>(msg.wParam);
 }

int CALLBACK WndProc(...)
{
    ...
    WNDCLASSEX wc;
    ...
    wc.lpfnWndProc = DefWindowProc;
    ...
    HANDLE threadHandle = 0;
    // use "this" as the 4th parameter when implementing in a class
    threadHandle = CreateThread(0, 0, MyAwesomeEventLoop, 0, 0, 0);

    ... // you are now free to do whatever you want! :)

    // waits untill the thread finishes
    // hopefully because PostQuitMessage(0) was called
    WaitForSingleObject(threadHandle, INFINITE);
    DWORD returnValue = 0;
    GetExitCodeThread(threadHandle, &returnValue);
    CloseHandle(threadHandle);
    ...

    return static_cast<int>(returnValue);
 }

What do you guys think?

like image 596
acpluspluscoder Avatar asked Dec 03 '11 08:12

acpluspluscoder


1 Answers

GetMessage docs on MSDN:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx

Read the first sentence: "Retrieves a message from the calling thread's message queue."

The message queue for a window is tied to the thread it was created on. Since you created your window on the main thread, your event loop running on a new thread will just not receive any messages for that window. If you want to run the event loop on another thread, you will need to create the thread first, then create your window on that thread.

like image 198
Andrew Avatar answered Nov 15 '22 02:11

Andrew