7

マルチスレッド、コールバック、win32 api関数、およびその他の厄介な問題をいじりながら、アイデアイベントを受け取りました。(へへへ)

グローバル(またはクラスを設計するときに静的)コールバック関数を定義する代わりに、ウィンドウクラスを登録するときに割り当てDefWindowProcてからlpfnWndProc、イベントループ全体を別のスレッドで実行した場合はどうなりますか?

このように、クラスにコールバックを実装する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);
 }

皆さんはどう思いますか?

4

2 に答える 2

14

MSDN の GetMessage ドキュメント:

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

最初の文を読んでください: 「呼び出しスレッドのメッセージ キューからメッセージを取得します。」

ウィンドウのメッセージ キューは、ウィンドウが作成されたスレッドに関連付けられています。メイン スレッドでウィンドウを作成したため、新しいスレッドで実行されているイベント ループは、そのウィンドウのメッセージをまったく受け取りません。別のスレッドでイベント ループを実行する場合は、最初にスレッドを作成してから、そのスレッドでウィンドウを作成する必要があります。

于 2011-12-03T11:32:08.243 に答える
2

これは、一般的なイベント ループ内にウィンドウ クラス固有のイベント処理コードがあることを除けば、実際には何のメリットもありません。バックグラウンド作業が必要な場合は、ワーカー スレッドを使用します。GUI とイベント リアクタをメイン スレッド内に保持し、ドキュメントに従ってコールバックを使用します。

また、インスタンスがウィンドウを処理するクラスがある場合は、シングル スレッド コードであってもそれらをグローバルにしないでください (そうしないと、将来、面倒なリファクタリングに苦しむことになります)

于 2011-12-03T09:35:57.237 に答える