关于在没有WndProc的情况下运行win32事件循环的不同方法的想法?

问题描述 投票:5回答:2

在搞乱多线程,回调,win32 api功能以及其他麻烦的问题时,我收到了一个想法事件。 (呵呵呵)

如果不是在定义全局(或设计类时是静态的)回调函数,而是在注册窗口类时为DefWindowProc分配lpfnWndProc,然后在单独的线程上运行整个事件循环,该怎么办?

这样,当this和主线程的执行继续时,我不必破解implementing the callback in a class问题,让你摆脱那个上帝抛弃的循环,允许你做任何事情,甚至打开另一个窗口(耶!)

“正常”方式:

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);
}

我新发现的令人敬畏的方式:

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);
 }

你们有什么感想?

c++ windows multithreading winapi event-loop
2个回答
13
投票

MSDN上的GetMessage文档:

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

阅读第一句话:“从调用线程的消息队列中检索消息。”

窗口的消息队列与创建它的线程相关联。由于您在主线程上创建了窗口,因此在新线程上运行的事件循环将不会收到该窗口的任何消息。如果要在另一个线程上运行事件循环,则需要先创建线程,然后在该线程上创建窗口。


2
投票

除了现在你在一般事件循环中有特定于窗口类的事件处理代码之外,这并不能真正为你买任何东西,这很简单。如果您需要后台工作,请使用工作线程。将GUI和事件反应器保持在主线程内,并使用所记录的回调。

如果你有一个实例处理窗口的类,你不应该在单线程代码中使它们全局化(或者你将来会遭受痛苦的重构)。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.