Introduzione alle API Win32

Capitolo 4: dialoghi

Le "finestre" sono oggetti astratti (cui normalmente, ma non sempre, corrisponde anche una rappresentazione su schermo) sulle quali si impernia gran parte del modello di programmazione Windows.

Ogni finestra ha tanti attributi, di svariati ordini, il più importante del quali è la classe della finestra. Nella programmazione Windows, spesso si definiscono classi speciali per le finestre del nostro programma. Comunque, possiamo rimandare la discussione sulla definizione di nuove classi, perchè il sistema ne fornisce parecchie, già definite, con le quali si possono già scrivere molti utili programmi Windows, e ci converrà dunque iniziare presentando queste classi già esistenti ed usabili.

Una delle più importanti categorie di finestre predefinite in Windows sono i dialoghi. I dialoghi possono essere creati dinamicamente dal nostro programma, ma è più abituale, e spesso comodo, definirne invece l'aspetto a priori, inserendo un "modello di dialogo" ("dialog template") come risorsa del nostro programma.

Le risorse di un programma vengono normalmente descritte in un file di testo chiamato NOME.RC, che un "resource compiler" provvede a tradurre in un vero e proprio "file di risose", NOME.RES; il linker, poi, o un programma ausiliario, inserisce questo .RES nel file eseguibile .EXE del programma (o, anche, in una libreria a caricamento dinamico, cioè un file di tipo .DLL).

I file .RC sono spesso preparati con l'ausilio di programmi speciali, "editor di dialoghi" (ad esempio, ve n'è uno incluso nel "Platform SDK" già menzionato, e un altro fa parte del pacchetto LCC-Win32, pure già menzionato), ma essi possono anche benissimo essere scritti come file di testo con un qualsiasi text editor; da quest'ultimo punto di vista, RC è un linguaggio, con la propria sintassi, e la propria semantica -- non un linguaggio di programmazione, ma un linguaggio, specializzato, di descrizione di dialoghi ed altre risorse Windows.

Un semplice dialogo "vuoto" può, ad esempio, essere descritto così, nel file di testo MIODIALOGO.RC:

#include <windows.h> MioDialogo DIALOG DISCARDABLE 0, 0, 186, 92 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Un Dialogo vuoto" FONT 8, "MS Sans Serif" BEGIN END

Qui, MioDialogo è l'identificatore (in questo caso, un identificatore-stringa) della risorsa di tipo dialogo; sulla stessa riga seguono la keyword DIALOG, gli attributi (qui, DISCARDABLE), e le "coordinate" (le prime due, la "origine", non sono significative; le seconde danno la dimensione del dialogo, in una unità di misura, detta dialog unit, che corrisponde a un diverso numero di pixel a seconda del font usato, proporzionalmente alle dimensioni medie dei caratteri del font).

La seconda riga descrive lo "stile" della finestra di dialogo; qui, definiamo un "classico" dialogo, con barra di titolo ("caption") e menu di sistema. Si tratta di "macro" (definite da un tipico #define del preprocessore C); è perchè il resource-compiler conosca queste macro, che includiamo il solito <windows.h>.

La terza riga indica il contenuto della barra di titolo; la quarta, il font da usare.

Il tutto si conclude con una coppia di righe BEGIN e END; non vi è nulla fra di loro, perchè questo dialogo è vuoto, ma, normalmente, vi sarebbero elencati i "controlli" (altre finestre di classi predefinite), ciascuno con i propri vari attributi di stile, coordinate, dimensioni, ecc.

 

Per usare questo dialogo (che supponiamo di avere inserito come risorsa nel nostro EXE, col passaggio, come già descritto, attraverso la forma compilata .RES) il modo più semplice è usare la API DialogBoxParam:

int DialogBoxParam(HINSTANCE hInstance, LPCTSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc LPARAM dwInitParam)

Abbiamo già incontrato il tipo HINSTANCE e quello HWND -- fortunatamente, anche in questo caso si può rimandare lo studio dei loro significati, e passare solo zero per i parametri di questi tipi. Così pure, abbiamo incontrato LPCTSTR (const char*, in pratica); come nome del template, parametro lpTemplateName, si passerà, appunto, la stringa che è il nome della risorsa template da usare.

Il tipo DLGPROC è un puntatore a funzione, e, nel relativo parametro, passeremo il puntatore alla "dialog procedure" il cui codice caratterizzerà il comportamento del nostro dialogo; LPARAM (praticamente, un "token" di 32 bit, che possono avere diversi significati a seconda dei contesti) identifica un nostro parametro che il sistema passerà alla nostra dialog procedure nella chiamata di inizializzazione del dialogo (sarà dunque solo a codice scritto da noi stessi, che potrà eventualmente interessare il suo valore); per ora, si possono ignorare anch'essi, e passare 0 per ciascuno.

Abbiamo così il nostro secondo programma Windows (trascuriamo, d'ora innanzi, gli include di sistema; inoltre, ripetiamo, nell'EXE dovranno essere state inserite le risorse corrispondenti al nostro .RC suvvisto):

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

Eseguendo questo programma, apparirà il dialogo vuoto prima disegnato. Noteremo, però, che, pur essendo esso dotato della normale "crocetta" in alto a destra, cliccando quest'ultima (il che, ci aspetteremmo, dovrebbe chiudere il dialogo), non succederà nulla... l'unico modo di terminare l'applicazione sarà l'uso del Task Manager di Win/Nt, o, in Win95 o Win98, un Ctl-Alt-Del seguito dall'"End Task" per questa nostra "applicazione". Perchè, ci chiediamo...?


Capitolo 3: un minimo di I/O
Capitolo 5: messaggi
Elenco dei capitoli