2

メッセージ ハンドラ内からメッセージ ループを正しく実行できません。実際には、DialogBox() がメッセージを処理する方法を複製し、すべてのウィンドウ処理を差し引いています。

システム メニューを開く WM_SYSKEYDOWN イベントがサブループへのエントリもトリガーする場合を除いて、メッセージ ハンドラー内から GetMessage() を呼び出すだけでほとんど機能します。この奇妙なことが起こった後、キーの押下が飲み込まれ、システム メニューに関連する WM_MOUSEMOVE メッセージがメイン ウィンドウに送信されます。

記録として、これは Windows 8 と XP の両方で発生します。

いくつかのコンテキストを提供するために、(ウィンドウのない) ワーカー スレッドがサーバーとして機能するメイン ウィンドウへの SendMessage 呼び出しをブロックすることで通信するスレッド モデルを試みています。これらのアクションにはさらに入力が必要な場合や、他の I/O に依存する場合があるため、通常のメッセージは、応答の準備ができるまで処理する必要があります。

前回ここに投稿したときと同じように、これが私の側の基本的な間違いまたは誤解であることはかなり確信していますが、自分で何が間違っているのかをうまく理解できないようです.

これが私の再現ケースです。ALT+SPACE を押してシステムメニューを開いてからナビゲートしてみてください。

#include <windows.h>

BOOL update;

LRESULT WINAPI WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    MSG msg;
    char text[256];
    switch(uMsg) {
    case WM_DESTROY:
        ExitProcess(0);
    // Trigger an update on input
    case WM_SYSKEYDOWN:
        update = TRUE;
        break;
    // Display the update from the worker thread, returning once it is time to
    // ask for the next one
    case WM_USER:
        wsprintf(text, TEXT("%u"), (unsigned int) lParam);
        SetWindowText(hwnd, text);
        while(!update && GetMessage(&msg, NULL, 0, 0) > 0) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        update = FALSE;
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

DWORD WINAPI ThreadProc(void *hwnd) {
    // Submit updates as quickly as possible
    LONG sequence = 1;
    for(;;)
        SendMessage(hwnd, WM_USER, 0, sequence++);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCommandLine, int nCmdShow) {
    HWND hwnd;
    MSG msg;

    // Create our window
    WNDCLASS windowClass = { 0 };
    windowClass.lpfnWndProc = WindowProc;
    windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    windowClass.hCursor = NULL;
    windowClass.lpszClassName = TEXT("Repro");
    RegisterClass(&windowClass);
    hwnd = CreateWindow(TEXT("Repro"), TEXT("Repro"),
        WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
        hInstance, 0);
    // Launch the worker thread
    CreateThread(NULL, 0, ThreadProc, hwnd, 0, NULL);
    // And run the primary message loop
    while(GetMessage(&msg, NULL, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}
4

1 に答える 1

1

モーダル メッセージ ループはまったく問題ありません。Raymond Chen は、モーダル メッセージ ループの適切な記述に関する一連の記事を執筆しています

私が気づいたことの 1 つ: スレッドはメッセージを送信するのではなく、投稿する必要があります。SendMessageウィンドウ プロシージャを直接呼び出します。も使用しないでくださいPostThreadMessage。これは、目に見える UI のないスレッド用に設計されています (ネストDispatchMessageされたスレッドはスレッド メッセージをディスパッチする方法がわからないため、メッセージがドロップされます)。

于 2013-10-12T19:17:04.577 に答える