Jeśli MessageBox () / related są synchroniczne, dlaczego moja pętla wiadomości nie zamarza?

Dlaczego tak nazywam funkcję Windows z pozoru synchroniczną?MessageBox() wewnątrz mojej pętli wiadomości sama pętla nie zamarza, jakbym dzwoniłSleep() (lub podobna funkcja)? Aby zilustrować mój punkt widzenia, weź następujący szkieletWndProc:

int counter = 0;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_CREATE:
             SetTimer(hwnd, 1, 1000, NULL); //start a 1 second timer
             break;
        case WM_PAINT:
             // paint/display counter variable onto window
             break;
        case WM_TIMER: //occurs every second
             counter++;
             InvalidateRect(hwnd, NULL, TRUE); //force window to repaint itself
             break; 
        case WM_LBUTTONDOWN: //someone clicks the window
             MessageBox(hwnd, "", "", 0);
             MessageBeep(MB_OK); //play a sound after MessageBox returns
             break;
        //default ....
    }
    return 0;
}

W powyższym przykładzie główną funkcją programu jest uruchamianie zegara i wyświetlanie wartości licznika co sekundę. Jeśli jednak użytkownik kliknie nasze okno, program wyświetli okno komunikatu, a następnie wyemituje sygnał dźwiękowy po zamknięciu skrzynki.

Oto, gdzie robi się interesująco: możemy powiedziećMessageBox() jest funkcją synchroniczną, ponieważMessageBeep() nie działa, dopóki okno komunikatu nie zostanie zamknięte. Jednak zegar nadal działa, a okno jest odświeżane co sekundę, nawet gdy wyświetlane jest okno komunikatu. Więc gdyMessageBox() najwyraźniej wywołanie funkcji blokującej, inne wiadomości (WM_TIMER/WM_PAINT) nadal mogą być przetwarzane. To dobrze, chyba że zastąpię MessageBox innym wywołaniem blokującym, takim jakSleep()

    case WM_LBUTTONDOWN:
         Sleep(10000); //wait 10 seconds
         MessageBeep(MB_OK);
         break;

To całkowicie blokuje moją aplikację, a przetwarzanie wiadomości nie następuje przez 10 sekund (WM_TIMER/WM_PAINT nie są przetwarzane, licznik się nie aktualizuje, program „zawiesza się” itp.). Więc dlaczego tak jestMessageBox() pozwala kontynuować przetwarzanie wiadomościSleep() nie? Biorąc pod uwagę, że moja aplikacja jest jednowątkowa, co to takiegoMessageBox() czy ta funkcja jest dostępna? Czy system „replikuje” mój wątek aplikacji, dzięki czemu może zakończyćWM_LBUTTONDOWN kod razMessageBox() jest zrobione, a jednocześnie pozwala oryginalnemu wątkowi przetwarzać inne wiadomości w międzyczasie? (to było moje niewykształcone przypuszczenie)

Z góry dziękuję

questionAnswers(2)

yourAnswerToTheQuestion