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

发布于 2024-12-19 11:17:21 字数 2110 浏览 1 评论 0 原文

在忙着处理多线程、回调、win32 api 函数和其他麻烦事时,我收到了一个想法事件。 (呵呵)

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

这样,当 this 问题。 "nofollow">在类中实现回调 主线程的执行继续,将你从那个被上帝遗弃的 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);
}

我新发现的很棒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);
 }

你们觉得怎么样?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

戏舞 2024-12-26 11:17:21

MSDN 上的 GetMessage 文档:

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

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

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

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.

无妨# 2024-12-26 11:17:21

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

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

That doesn't really buy you anything, except now you have window class-specific event handling code in a generic event loop, which is plain ugly. If you need background work, use worker threads. Keep the GUI and the event reactor inside the main thread, and use callbacks as documented.

And if you have a class whose instances handle windows, you shouldn't make them global even in single-threaded code (or you will suffer painful refactoring in the future).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文