giovedì 25 giugno 2009

Introduzione alle API Win32, Parte 4/6 - DevSpy.com

 

Introduzione alle API Win32, Parte 4/6

di Mastersgn, del 30 gennaio 2007 C/C++

Dopo aver creato una finestra di dialogo, introduciamo il concetto di evento e sviluppiamo la gestione di un particolare evento: la chiusura del dialogo. Infine, inseriamo un controllo nel dialogo come premessa alla lezione successiva.

Procedura del dialogo

Nell'articolo precedente abbiamo lasciato una domanda in sospeso: Perché non è possibile chiudere la finestra di dialogo? Prima di rispondere dobbiamo comprendere un particolare importante:

Quando interagiamo con un dialogo - ovvero lo ridimensioniamo, chiudiamo o clicchiamo su un controllo in esso presente - compiamo azioni chiamate eventi.

Ogni finestra possiede i propri eventi e, a fronte dell'attivazione di questi, può rispondere in determinati modi, che ovviamente saremo noi a decidere. Di conseguenza, quando chiudiamo il nostro dialogo in realtà inviamo un messaggio di chiusura della finestra alla procedura di gestione dell'evento: ogni dialogo dispone di una procedura per gestire i possibili eventi.

A questo punto è facile intuire che il dialogo creato nel precedente articolo non si chiudeva perchè non possedeva una propria procedura di gestione degli eventi, compreso la chiusura della finestra stessa.

Dunque, modificamo il codice del file main.c, come segue:

#include <windows.h>


BOOL CALLBACK dlgProc(HWND hwndDlg,UINT dlgMsg,WPARAM wParam,LPARAM lParam);


int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
DialogBoxParam(0,"MioDialogo",0,dlgProc,0);
return 0;
}


BOOL CALLBACK dlgProc(HWND hwndDlg,UINT dlgMsg,WPARAM wParam,LPARAM lParam)
{
switch(dlgMsg)
{
case WM_CLOSE:
EndDialog(hwndDlg,0);
return TRUE;
break;
}
return 0;
}


Compiliamo nuovamente l'applicazione: ora la finestra è in grado di chiudersi correttamente.



Procedure e messaggi



Incontriamo una funzione utilizzata, appunto, come procedura del dialogo per la gestione degli eventi. Analizziamone il prototipo:



BOOL CALLBACK dlgProc(HWND hwndDlg,UINT dlgMsg,WPARAM wParam,LPARAM lParam);



  • La funzione restituisce un tipo BOOL (valore 0 oppure 1) che può essere usato per conoscere l'esito della procedura.


  • dlgProc è il nome che abbiamo scelto per la propcedura.


  • Il parametro di tipo HWND (che chiamiamo hwndDlg) riceve l'handle del dialogo. Ci servirà nella procedura stessa (come primo parametro nella chiamata a EndDialog()).


  • UINT dlgMsg è il codice del messaggio. Viene passato alla procedura al verificarsi di un determinato evento (nel nostro caso WM_CLOSE per chiudere la finestra).


  • WPARAM ed LPARAM per ora li ingoriamo; li analizzeremo più avanti.



Adesso analizziamo il corpo della procedura:



switch(dlgMsg)
{
case WM_CLOSE:
EndDialog(hwndDlg,0);
return TRUE;
break;
}


Troviamo uno switch sulla variabile dlgMsg: nel caso in cui il codice del messaggio corrisponda a  WM_CLOSE, la procedura chiude il dialogo utilizzando la funzione EndDialog(). Dunque, a fronte dell'evento di chiusura del dialogo, il sistema spedisce un messaggio WM_CLOSE alla procedura di gestione, "chiedendo" al dialogo di chiudersi.



Funzione EndDialog()



BOOL EndDialog(
HWND hDlg,
int nResult
);



  • Al parametro di tipo HWND passiamo l'handle del dialogo da chiudere. Nel nostro caso hwndDlg (se stesso).


  • A int nResult passiamo 0 (zero), e non ce ne interessiamo ulteriormente.



Osserviamo nuovamente la funzione di creazione del dialogo:



 DialogBoxParam(0,"MioDialogo",0,dlgProc,0);


Al quarto parametro (DLGPROC lpDialogFunc), passiamo il nome della procudura del dialogo, dlgProc appunto.



Riassumendo



Ogni dialogo possiede una procedura interna per gestire gli eventi che si possono verificare, tra cui anche la chiusura del dialogo stesso.




  • Abbiamo visto che al verificarsi di un evento, il sistema invia alla procedura del dialogo il messaggio corrispondente a questo evento. Nel nostro caso si è trattato della chiusura della finestra, ma potrebbe trattarsi di qualsiasi altro evento, come il click su un controllo.


  • Osserviamo il corpo della procedura: nel caso in cui (istruzione switch) il codice del messaggio (in questa procedura l'abbiamo chiamato dlgMsg) corrisponda a WM_CLOSE (evento di chiusura), allora chiudiamo il dialogo attraverso la chiamata alla funzione EndDialog().


  • La costante WM_CLOSE è un valore predefinito dell'ambiente. Ne esite uno per definire ciascun evento.


  • Nell'istruzione di creazione del dialogo DialogBoxParam(0,"MioDialogo",0,dlgProc,0), il secondo parametro indica il dialogo così come è stato definito nel nostro file resource.rc, mentre il quarto parametro identifica la procedura dello stesso.



Come esercizio per consolidare il tutto vi consiglio di riscrivere un'altro progetto uguale a questo, ma con nome di variabili, funzioni, costanti e parametri diversi (ad eccezione, ovviamente, delle costanti di ambiente!).



Aggiungiamo un controllo static



A questo punto, per concludere l'esercizio, inseriamo un semplice controllo nel nostro dialogo. Modifichiamo il file resource.rc in questo modo:



#include <windows.h>

MioDialogo DIALOG 20, 30, 180, 100
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialogo vuoto"
FONT 10, "Ms Sans Serif"
BEGIN
  CTEXT "Sono un esempio di controllo static",101,16,18,144,33
END


Compilate il programma e vedrete il nuovo controllo all'interno della finestra. Nel prossimo appuntamento, vedremo come inviare e ricevere messaggi verso il controllo.




Introduzione alle API Win32, Parte 4/6 - DevSpy.com

Nessun commento:

Posta un commento