Introduzione alle API Win32

Capitolo 15: un esempio (2)

Per concludere il nostro esempio, iniziato al capitolo scorso, dobbiamo ancora scrivere tre funzioni, che abbiamo scelto di chiamare OnDlgClose, OnDlgInitDialog, e OnDlgCommand, per gestire i relativi messaggi windows (WM_CLOSE, WM_INITDIALOG, e WM_COMMAND rispettivamente).

Di queste, la più semplice è certo la OnDlgClose:

void OnDlgClose(HWND hWnd) { EndDialog(hWnd,0); } Se solo la programmazione Windows fosse tutta così semplice...!-)

 

Più interessanti, certamente, le altre due funzioni. Vediamone intanto gli "scheletri", ancora vuoti, così da potere, se non altro, mettere insieme un primo abbozzo complessivo di programmino, compilarlo, e provarlo:

BOOL OnDlgInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { // qui: azioni di inizializzazione return TRUE; } void OnDlgCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { // qui: azioni in risposta ai comandi } Spero che i significati dei vari parametri siano già chiari dai capitoli precedenti.

 

Eseguendo questa versione "scheletrica", naturalmente, non è che vediamo gran che -- visto che non abbiamo detto nulla, tra l'altro, su quali bitmap e icone mostrare! Procediamo dunque subito a completare l'inizializzazione.

Dobbiamo caricare-e-mostrare quattro bitmap sui quattro bottoni; la ripetitività del compito già ci dice che vorremo scrivere per questo scopo una funzione apposita, e chiamarla quattro volte. Per "simmetria", delegheremo ad un'altra funzione anche il compito di caricare-e-mostrare l'icona sullo static... se le scriviamo bene, sono funzioni che possono comunque tornarci utili anche in futuro (se le mettiamo in una libreria, oppure, ahimè!, col copia-e-incolla).

L'intera funzione di inizializzazione del dialogo si potrebbe dunque presentare così:

BOOL OnDlgInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { Mostra_BM_bottone(OBM_LFARROW, hwnd, IDC_BUTTON1); Mostra_BM_bottone(OBM_RGARROW, hwnd, IDC_BUTTON2); Mostra_BM_bottone(OBM_UPARROW, hwnd, IDC_BUTTON3); Mostra_BM_bottone(OBM_DNARROW, hwnd, IDC_BUTTON4); Mostra_Icona_static(IDI_HAND, hwnd, IDC_STICON); return TRUE; } Già, ma -- cosa sono quelle OBM_eccetera, e IDI_eccetera...?

Sono gli identificatori delle risorse "OEM" (sigla che dovrebbe stare per "Original Equipment Manufacturer", ma cosa queste parole c'entrino in questo contesto, mah!); in pratica, risorse "di sistema" di Windows, che qualsiasi applicazione, se le servono, può usare. (Le OBM_ecc sono numeri, le IDI_ecc, stringhe -- viva la simmetria, regolarità, e semplicità...!-).

I quattro valori OBM_ecc che abbiamo usato identificano quattro bitmap di "freccia", nelle quattro direzioni -- proprio quel che vogliamo per i nostri pushbutton; la IDI_HAND è una "icona di errore", che ho scelto solo in quanto sempre "ben visibile".

Oltre all'identificatore della risorsa "OEM" da usare, le due funzioncine (che ancora dobbiamo scrivere) prendono l'handle del dialogo, e l'identificatore (numerico) del controllo su cui devono agire; questo garantisce una discreta generalità (si può, naturalmente, fare di meglio, ma per il momento ci può anche bastare).

Resta, dunque, da scrivere queste due funzioncine. Esse sono, per fortuna, di struttura abbastanza simile e semplice:

void Mostra_Icona_static(const char* ic_cod, HWND hDlg, int sta_cod) { HWND hSta = GetDlgItem(hDlg, sta_cod); HICON hi = LoadIcon(0,ic_cod); SendMessage(hSta,STM_SETICON,(WPARAM)hi,0); } Questa ottiene l'handle del controllo con la già vista API GetDlgItem, l'handle dell'icona con la (per noi nuova) API LoadIcon, e, con un semplice messaggio STM_SETICON, "congiunge" le due nel modo desiderato.

L'API LoadIcon prende due parametri: il primo è una HINSTANCE (tipo che abbiamo già incontrato, e risolutamente ignorato...:-), e, passando il valore 0 per questo parametro, le indichiamo che vogliamo caricare una risorsa di sistema; il secondo parametro, invece, è l'identificatore della risorsa stessa.

void Mostra_BM_bottone(int bm_cod, HWND hDlg, int but_cod) { HWND hBut = GetDlgItem(hDlg, but_cod); HBITMAP hi = LoadBitmap(0,MAKEINTRESOURCE(bm_cod)); SendMessage(hBut,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)hi); }

Proprio la stessa logica -- appena più complicata per dettagli come la necessità di "convertire" l'identificatore di risorsa da int a stringa (cosa che fa per noi la macro MAKEINTRESOURCE, naturalmente), e le complicazioni del messaggio BM_SETIMAGE, che richiede come wParam l'indicazione se stia caricando una bitmap o un'icona, e prende l'handle come lParam. Piccolezze, per fortuna!

 

Possiamo dunque compilare nuovamente il nostro piccolo esempio, e, questa volta, dovremmo avere un "look" un poco più soddisfacente... ci sono ancora dei problemini, naturalmente, tipo il fatto che il look non è del tutto soddisfacente, e la secondaria considerazione che l'intero programma non fa ancora nulla (nè mai farà nulla, sinchè non ci decideremo a farlo rispondere ai comandi...:-). Meglio -- così avremo qualcosa di cui parlare al prossimo capitolo!-)


Capitolo 14: un esempio (1)
Capitolo 16: un esempio (3)
Elenco dei capitoli