Domanda

Sto sviluppando un'applicazione che si presenta principalmente in questo modo:

while (true)
{
    while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
    {
       TranslateMessage(&Msg);
       DispatchMessage(&Msg);
    }
    DoSomething();
    Sleep(1);
}

Quello che ho notato è che DoSomething () non viene chiamato quando clicco sulla barra dei menu (che visualizza le opzioni del menu). Ho osservato che i blocchi di chiamata DispatchMessage il ciclo messae fino a quando esco della barra dei menu!

Come potevo evitare questo comportamento ??

Grazie!

È stato utile?

Soluzione

Il motivo è perché Windows assume l'elaborazione dei messaggi quando viene visualizzato qualcosa di simile a un menu dell'applicazione o finestra di messaggio, e che ciclo di messaggi che Windows utilizza non chiamerà il metodo DoSomething(). Questo può essere difficile da visualizzare, quindi cercherò di passare da ciò che sta accadendo:

  • Quando qualcuno apre il menù, viene inviato un messaggio alla finestra dicendogli di disegnare la finestra. DispatchMessage() invia il messaggio al tuo WndProc, come tutti gli altri messaggi.
  • Dal momento che non si gestisce questo messaggio, si passa a Windows (dal momento che il WndProc più che probabile chiama DefWindowProc)
  • Per quanto l'operazione di impostazione predefinita, Windows richiama il menu e inizia un altro ciclo di messaggi di default che non chiamerà DoSomething()
  • Questo ciclo recupera i messaggi destinati per l'applicazione e li invia alla propria applicazione chiamando WndProc, quindi l'applicazione non congelare e continua a funzionare (meno la chiamata DoSomething()).
  • Una volta che il menu è chiuso, il controllo verrà restituito al ciclo di messaggi (solo a questo punto sarà la chiamata DispatchMessage() dal ritorno fin dall'inizio)

In altre parole, quando viene visualizzato un menu, il vostro ciclo di messaggi viene sostituito da uno di default che assomiglia a questo (per esempio)

while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
} 

, che, come si può vedere, non chiamare il metodo di DoSomething().

Per verificare ciò, provare a mettere in pausa il codice in un debugger quando viene visualizzato nessun menu, e mentre uno è. Se si vede lo stack di chiamate, si vedrà che, quando viene visualizzato un menu, i messaggi vengono elaborati da un ciclo di messaggi di Windows, non dal sottoscritto.

L'unica soluzione mi viene in mente (senza multithreading) è se si avvia un timer e gestire il messaggio WM_TIMER chiamando DoSomething(), ma che non sarebbe una soluzione perfetta (in quanto presumo il vostro intento è quello di chiamare DoSomething() solo quando c'è sono messaggi lasciati per elaborare).

Altri suggerimenti

Spin off traduzione e spedizione dei Msg in un thread separato.

Finché DoSomething non dipende spedizione dei Msg.

Anche se potrei voler capire perché la spedizione è il blocco; è questo comportamento normale atteso?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top