2011-06-26 24 views
9

Nel oggetto GUI mia C++ dell'applicazione Ho il seguente nella procedura finestra principale:PostMessage() ha esito positivo, ma il mio codice di elaborazione dei messaggi non riceve il messaggio

case WM_SIZE: 
    { 
     OutputDebugString(L"WM_SIZE received.\n"); 
     RECT rect = {0}; 
     GetWindowRect(hwnd, &rect); 
     if (!PostMessage(0, GUI_MSG_SIZECHANGED, w, MAKELONG(rect.bottom - rect.top, rect.right - rect.left))) { 
      OutputDebugString(L"PostMessage failed.\n"); // <--- never called 
     } 
    } 

    return 0; // break; 

L'oggetto GUI ha anche il seguente metodo getMessage() :

int GUI::getMessage(MSG & msg) { 
    BOOL result = 0; 

    while ((result = GetMessage(&msg, 0, 0, 0)) > 0) { 
     if (msg.message > (GUI_MSG_BASE-1) && msg.message < (GUI_MSG_LAST+1)) { 
      OutputDebugString(L"GUI message received.\n"); 
      break; 
     } 
     else { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
    } 

    return result; 
} 

l'oggetto applicazione chiama questo metodo nel modo seguente:

while ((result = _gui.getMessage(msg)) > 0) { 
    switch (msg.message) { 
     // TODO: Add gui message handlers 
     case GUI_MSG_SIZECHANGED: 
      OutputDebugString(L"GUI_MSG_SIZECHANGED received.\n"); 
      _cfg.setWndWidth(HIWORD(msg.lParam)); 
      _cfg.setWndHeight(LOWORD(msg.lParam)); 
      if (msg.wParam == SIZE_MAXIMIZED) 
       _cfg.setWndShow(SW_MAXIMIZE); 
      else if (msg.wParam == SIZE_MINIMIZED) 
       _cfg.setWndShow(SW_MINIMIZE); 
      else if (msg.wParam == SIZE_RESTORED) 
       _cfg.setWndShow(SW_SHOWNORMAL); 
      break; 
    } 
} 

L'oggetto dell'applicazione è interessato alle dimensioni della finestra poiché memorizza queste informazioni in un file di configurazione.

Quando ho eseguito questo debugger di Visual Studio, la finestra di output si presenta così dopo il ridimensionamento della finestra:

WM_SIZE received. 
GUI message received. 
GUI_MSG_SIZECHANGED received. 
WM_SIZE received. 
WM_SIZE received. 
WM_SIZE received. 
WM_SIZE received. 
...etc... 

Il PostMessage() la funzione non manca mai, ma sembra inviare solo GUI_MSG_SIZECHANGED (#defined come WM_APP + 0x000d) la prima volta che viene gestito WM_SIZE, ovvero subito dopo aver gestito WM_CREATE.

Non ho idea di cosa potrebbe causare questo. Ho provato a utilizzare SendMessage e PostThreadMessage ma il risultato è lo stesso. Leggere anche la documentazione sulla gestione dei messaggi di MSDN, ma non è stato possibile trovare cosa c'è di sbagliato nel mio codice.

Qualcuno può aiutare?

+4

Perché non si esegue un normale ciclo di messaggi. Che diavolo è il punto del ciclo 'while' in' GUI :: getMessage'? Sembra che tu abbia due pompe di messaggi nidificati !! Non riesco a capirmi del tutto. Se si eseguisse un normale messaggio, sarebbe più facile essere motivati ​​a cercare di rispondere alla domanda. Così com'è, si può solo immaginare quale altra stranezza sta succedendo. –

+0

E '(msg.message> (GUI_MSG_BASE-1) && msg.message <(GUI_MSG_LAST + 1))' piuttosto che usare '> =' e '<='? Perché? –

+1

Provate ad aggiungere un po 'di output di debug quando entrate e uscite dalla funzione 'GUI :: getMessage' e dopo il ciclo intorno a' _gui.GetMessage'. Penso che sia qualcosa nel tuo flusso di controllo del programma che è il problema, ma non riesco a individuare esattamente dove. –

risposta

6

L'hacking di un loop di messaggi personalizzato è qualcosa che vivrai a rimpiangere un giorno. Lo colpisci presto.

Non postare messaggi con un handle di finestra NULL, possono funzionare solo se è possibile garantire che il programma esegua sempre solo il ciclo personalizzato dei messaggi. Non puoi dare una simile garanzia. Questi messaggi cadono nel bucket di bit non appena si avvia una finestra di dialogo o Windows decide di pompare un loop di messaggi. Qual è il caso in cui l'utente ridimensiona una finestra, la logica di ridimensionamento è modale. Windows pompa il proprio ciclo di messaggi, WM_ENTERSIZEMOVE lo annuncia. Questo è anche il motivo per cui PostThreadMessage è malvagio se il thread è in grado di visualizzare qualsiasi finestra. Anche un MessageBox è fatale. DispatchMessage non può consegnare il messaggio.

Creare una finestra nascosta che funge da controller. Ora è possibile rilevare GUI_MSG_SIZECHANGED nella sua procedura di finestra e non sono necessari accessi al ciclo dei messaggi. Quel controller non è di rado la finestra principale della tua app btw.

+0

Anche se non mi piace l'idea di una finestra nascosta nel mio oggetto app (come sto cercando di mantenere il codice GUI nel mio oggetto GUI), questo è probabilmente quello che finirò facendo se non riesco a capire una soluzione più elegante. Per favore, leggi la mia risposta a David, forse hai un bel input per la mia domanda di progettazione OO. – Jehjoa

+0

Sto bene con i messaggi di thread che cadono sul pavimento durante i loop di dimensionamento modali, ma poi * come passa il primo *? :) –

+1

@ Frédéric - il primo è probabilmente un WM_SIZE dalla creazione della finestra iniziale. Qualcosa del genere. –

Problemi correlati