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:
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:
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):
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