【问题标题】:Thoughts on a different way to running a win32 event loop without WndProc?在没有 WndProc 的情况下运行 win32 事件循环的不同方式的想法?
【发布时间】:2012-01-12 02:05:51
【问题描述】:

在纠结多线程、回调、win32 api函数等麻烦事的同时,我收到了一个idea event。 (呵呵)

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

这样我就不必在implementing the callback in a class 时解决this 问题 主线程继续执行,将你从那个被上帝抛弃的 while 循环中解放出来,让你做任何事,甚至打开另一个窗口(耶!)

“正常”的方式:

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

你们怎么看?

【问题讨论】:

  • 好的想法应该被执行,而不是被批评。你会学到一些关于 Windows 体系结构的重要知识,消息队列具有线程关联性。您的 GetMessage() 调用永远不会收到消息。
  • 这些类型的查询并不真正适合 StackOverflow。请改用Programmers StackExchange
  • 赞成使用“虽然。”

标签: c++ windows multithreading winapi event-loop


【解决方案1】:

MSDN 上的 GetMessage 文档:

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

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

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

【讨论】:

    【解决方案2】:

    这并不能真正为您带来任何好处,除了现在您在通用事件循环中拥有特定于窗口类的事件处理代码,这简直是丑陋的。如果您需要后台工作,请使用工作线程。将 GUI 和事件反应器保留在主线程中,并按照文档说明使用回调。

    如果您有一个实例处理窗口的类,即使在单线程代码中也不应该将它们设为全局(否则您在未来遭受痛苦的重构)。

    【讨论】:

    • 例如它们是全局的。为什么通用事件循环很难看?
    • @acpluspluscoder:里面塞满了非通用代码的通用事件循环很难看。如果它们不是全球性的,那么无论如何您都在使用(Get/Set)WindowLongPtr,所以我不明白您所说的“我不必解决this 问题”是什么意思。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 2015-11-04
    • 1970-01-01
    相关资源
    最近更新 更多