DirectX/Message loop: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
m →‎Messaggi: accento
Nessun oggetto della modifica
Riga 16:
Questo codice andrebbe eseguito subito dopo lo ShowWindow del modulo precedente. '''GetMessage''' è una API che legge l'ultimo messaggio dal buffer e lo inserisce nella variabile puntata come primo argomento. Il secondo argomento è l'HANDLE della finestra da cui vogliamo ricevere i messaggi. Mettendolo a zero riceveremo anche i messaggi di altre finestre (create sempre dallo stesso processo ovviamente), nel caso in cui pensaste di crearne più di una. Gli ultimi due argomenti settati a zero, sono il codice minimo e massimo dei messaggi da ricevere. Per esempio ci potrebbe piacere leggere solo i messaggi con il tipo da 0x200 a 0x20E, ossia solo quelli legati strettamente alla gestione del mouse. Tutti gli altri verrebbero ignorati. Quando impostati a zero, non viene imposto alcun limite. Tutti i messaggi vengono interpretati. GetMessage ritorna 0 se il messaggio in arrivo è WM_QUIT, ossia il messaggio che chiede la chiusura del programma, e ritorna non-zero per ogni altro messaggio.
 
GetMessage, nonostante funzioni a dovere in normali applicazioni, purtroppo presenta una grave lacuna per un videogioco. Infatti nel caso in cui non ci fossero messaggi nel buffer, il processo viene messo in pausa fino all'arrivo di un nuovo messaggio. Questo per un videogame è inaccettabile, infatti le scene verrebbero mostrate solo in presenza di un messaggio. Per superare questo impedimento in applicazioni grafiche viene utilizzato '''PeekMessage'''. Questa funzione cerca un messaggio nel buffer e ritorna non-zero se un messaggio viene trovato e deve essere interpretato, e zero se non ci sono messaggi da leggere. In questo caso noi mostreremo una scena disegnata in DirectX.
<source lang="cpp">
MSG msg = { 0 };
Riga 31:
}
</source>
Se PeekMessage ritorna un valore diverso da zero, dobbiamo a questo punto gestire il messaggio. Questo normalmente si traduce con la chiamata di due funzioni:
<source lang="cpp">
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
</source>
'''TranslateMessage''' è una comoda funzione che trasforma alcuni codici in altri a noi più comprensibili. Ad esempio può tradurre lo [[w:en:Scancode|Scancode]] di un tasto, nel suo corrispondente nella tabella [[w:ASCII|ASCII]].
'''DispatchMessage''' invece chiamerà a sua volta una certa funzione responsabile di gestire i singoli messaggi. Quale funzione? Una creata da noi così:
<source lang="cpp">
LRESULT CALLBACK MsgHandler(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
{
}
</source>
 
Questa funzione il cui nome non è rilevante, prende quattro argomenti:
* L'HANDLE della finestra a cui era destinato il messaggio.
* Un codice che identifica il messaggio stesso.
* Due argomenti che possono anche non essere usati (ad esempio per il movimento del mouse ''potrebbero'' contenere le nuove coordinate x ed y del cursore)
La funzione viene chiamata da ''DispatchMessage'' per ogni messaggio ricevuto. Il valore di ritorno dipende dal tipo di messaggio. Generalmente ritornare zero vuol dire che il messaggio è stato correttamente elaborato (non vale per il 100% dei messaggi).
 
== Associare l'handler alla finestra ==
Come chiediamo però a Windows di chiamare proprio questa funzione con ''DispatchMessage''? Il puntatore a questa funzione deve essere inserito nel campo '''''lpfnWndProc''''' di WNDCLASSEX al momento della creazione. Questo era l'ultimo elemento della struttura che rimasto in attesa di spiegazioni ed ora WNDCLASSEX non ha più segreti per voi.
 
== Facciamo chiudere la finestra ==
A questo punto la finestra dovrebbe essere ben visibile, ma non avrete alcuna speranza di riuscire a chiuderla. Infatti il click sulla X rossa, o Alt-F4 inviano un messaggio di tipo WM_DESTROY alla finestra, che fino ad ora noi avevamo completamente ignorato. Vediamo come chiudere la finestra:
<source lang="cpp">
LRESULT CALLBACK MsgHandler(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
</source>
Ci sono qui due nuove funzioni. '''PostQuitMessage''' inserirà nel buffer dei messaggi un messaggio di tipo WM_QUIT. Quando il nostro Message Loop riceverà un WM_QUIT, il loop si interromperà facendo terminare il programma. L'argomento è il parametro da ritornare da WinMain.
 
'''DefWindowProc''' è invece una richiesta che facciamo a Windows di gestire il messaggio. In altre parole, non avendo alcun interesse nel gestire tutti i messaggi esistenti, chiediamo a Windows di gestire in modo ''standard'' tutti quelli che noi scartiamo.
 
{{Avanzamento|25%|12 ottobre 2011}}