Programmare l`interfaccia grafica in linguaggio C

Transcript

Programmare l`interfaccia grafica in linguaggio C
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Programmare l'interfaccia grafica
in linguaggio C
di Davide Giri
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Contenuti
1 Introduzione alla programmazione grafica
1.1
1.2
1.3
1.4
Prepariamo il necessario
windows.h , un'header tutto da scoprire
Rappresentazione dei dati secondo windows
Struttura del libro
2 Primi passi con le API
2.1 MessageBox
2.1.1 Utilizziamo la MessageBox
2.2 Inserire le variabili ad elementi grafici (wsprintf)
2.3 Finestra genitore e i suoi derivati (figli)
3 La nostra prima finestra personalizzata
3.1 Definiamo gli attributi della Window Class
3.1.1
3.1.2
3.1.3
3.1.4
LoadIcon
LoadCursor
Coloriamo lo sfondo (CreateSolidBrush)
CreateHatchBrush
3.2 Creiamo la finestra (CreateWindowEx)
3.3 Mostriamo la nostra finestra (ShowWindow)
3.4 Esaminiamo e processiamo i messaggi
3.4.1 GetMessage
3.4.2 DestroyWindow
3.4.3 PostQuitMessage
3.5 Analizziamo i messaggi della window
3.6 Inviamo i messaggi (SendMessage)
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
4 Una finestra già predefinita: il Dialogo
4.1 Includiamo i resource nel nostro progetto
4.2 Descriviamo il Dialogo
4.2.1
4.2.2
4.2.3
4.2.4
Specifichiamo la Dialog
Definiamo i suoi stili (STYLE)
Attribuiamo il titolo (CAPTION)
Impostiamo il carattere (FONT)
4.3 Richiamare la risorsa dialog (DialogBoxParam)
4.4 Riempiamo il dialogo
4.4.1 Esaminiamo i parametri comuni
4.5 Elementi static
4.5.0-1 Rendiamo attivi gli elementi static
4.5.1 Stringa di testo
4.5.1-1 Identificatori per soli testi
4.5.2 Immagine
4.5.3 Icona
4.5.3-1 Identificatori per sole icone
4.6 Elementi button
4.6.1 Pulsanti
4.6.1-1 Identificatori per soli pulsanti
4.6.2Radiobutton
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Capitolo 1
“Introduzione alla programmazione grafica”
Uno dei linguaggi da quasi sempre legato e particolarmente amato dai
programmatori di software per computer è il C.
In seguito ne seguì un altro, ovvero il C++, molto identico al predecessore per la
sua sintassi, ma con una innovativa tecnica di sviluppo, l' OOP (Object Oriented
Programming).
Questa programmazione orientata agli oggetti permette di raggruppare in una
classe le strutture dati e delle funzioni che operano su di esse, spesso
semplificando il prodotto finale sfornato dal programmatore rendendolo più
leggibile a terzi.
Tornando in tema, molti di voi avete iniziato ad apprendere la programmazione al
liceo o università e magari vi sarete anche chiesti come mai i vostri programmi,
realizzati con le conoscenze che vi erano date, erano poco presentabili, senza un
minimo di grafica a finestre come siete abituati a vedere.
Infatti vi si apriva quella classica finestra nera del DOS (Disk Operating System)
dove eventualmente si eseguivano le funzioni tramite essa, rendendo poco
professionale la vostra opera.
Tutto questo perché nel codice non veniva attribuito, o meglio inserito, nessun
elemento grafico che presentasse il testo di output, rendendo così il programma
un po' più user-friendly.
Anche il programmatore meno esperto può indurre che realizzare una cosa, che a
prima vista può sembrare così banale, invece richiede una conoscenza molto
approfondita del linguaggio e un'implementazione di centinaia di righe nel codice.
Ma non dovete abbattervi abbandonando l'idea di rendere i vostri programmi un
po' meno spartani dal solito; infatti ci hanno già pensato altri a semplificare il tutto
rendendo disponibili ai vari programmatori (non solo di C) delle librerie grafiche
più comunemente dette API (Application Programming Interface).
Le interfacce grafiche, denominate anche GUI (Graphic User Interface), a codice
compilato sembrano simili fra loro, ma esiste una più o meno vasta gamma di
librerie grafiche, con adattamenti e radici ben diverse in esse.
Le API di windows infatti hanno il fine di adattarsi solamente a sistemi win, questo
per parecchi può essere un lato in negativo, fornendo i componenti di base (quindi
non solo elementi grafici) alle applicazioni che scriveremo.
Avete letto bene, le APIwin32 (come tutte le API) non servono solamente per
costruire finestre, pulsanti e via discorrendo, ma offrono anche funzionalità (come
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
il trattamento di testi, etc...).
Forse vi sarete chiesti che significa il numero posto alla fine in APIwin32. Esso sta
ad indicare che le suddette API sono tutte scritte in 32 bit, ciò significa che al
passaggio ai 64 bit il nome muterà in APIwin64. Ma non avete timore, cambierà
solamente qualcosa all'interno della libreria (ci pensa la Microsoft), e
probabilmente ancora per molto si rimane a lavorare con applicativi a 32 bit, visto
che anche i nuovi processori a 64 hanno la possibilità di interpretarli benissimo.
Ho prima menzionato che esistono anche altre librerie per tali scopi. Una di queste
è la WxWidgets che non solo va bene per creare software che gireranno su
Windows, ma anche su altre piatteforme quali Unix (che comprende anche tutte le
distribuzioni Linux) e Mac. Inoltre la WxWidgets è opensource, quindi qualsiasi
programmatore un po' più esperto può rendersi partecipe a modificare tale
libreria, ottimizzandola o aggiungendoci nuove funzioni.
Detto questo però non voglio trascurare le API di Windows, infatti saranno esse a
proseguire il percorso in questo libro perché sono secondo me più semplici da
capire e questo è fondamentale per un apprendista programmatore ancora tra i
primi livelli.
1.1 Prepariamo il necessario
In questo libro saranno trattate le API di Windows utilizzando il linguaggio C,
quindi è necessario che avete una sua buona conoscenza prima di continuare in
questa lettura.
Ho deciso questo, potevo benissimo scegliere Python oppure Visual Basic, per il
motivo che esso sia il più vicino alle API (scritte in C). Un' altra ragione è
l'universalità del C, con codesto si possono scrivere da semplici programmetti a
sofisticati sistemi operativi (si pensi che Linux sia scritto per il 90% in C).
E' necessario, ovviamente, anche l'utilizzo di un buon compilatore che abbia già le
librerie installate che verranno poi utilizzate.
Uno di questi è il compilatore Dev-C++, il quale personalmente ritengo ottimo
perché
è
disponibile
gratuitamente
sulla
rete
(http://www.bloodshed.net/devcpp.html) e soprattutto per la sua facilità di
utilizzo.
Dev-C++ in realtà è il nome dell'interfaccia grafica del programma, il vero
compilatore che viene utilizzato dal programma stesso è il GCC.
Se vi ho consigliato Dev-C++ ovviamente è anche perché esso installa i file
header necessari al nostro tipo di programmazione.
Ho detto i file perché per programmare con le API ne serviranno circa più di venti,
ma non spaventatevi, non occorre includerle tutte una per una. Infatti basta
inserire solamente, tra le inclusioni dei nostri programmi, windows.h, il quale non
è altro che una pagina che va a richiamare tutti gli altri header.
Come si può intuire dalla denominazione, il nostro è un compilatore per sorgenti in
codice C++, ma a noi è indifferente visto che si può scrivere benissimo codice C;
basta selezionare 'C source file (*.c)' quando andremo a salvare il nostro
sorgente, per poi compilarlo e farlo eseguire premendo 'F9'.
Con compilatori per C++ infatti è possibile programmare anche in C, visto che il
primo è un sottoinsieme dell'altro.
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Capitolo 2
“Primi passi con le API”
Prima di tutto occorre sapere che i programmi in questo tipo di programmazione
sono leggermente diversi da come verrebbero scritti in C Standard.
Il C standard raggruppa tutte quelle funzioni e file header che possono benissimo
essere compilati e in seguito avviati su qualsiasi piattaforma. Naturalmente
windows.h non appartiene a queste, visto che diretto esclusivamente per la
creazione di applicativi windows.
Vi accorgerete che invece del solito main(), appartenente al C standard, se ne
trova una molto simile:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) {
// qui sarà steso il nostro programma
return 0;
}
Da come si può vedere, WinMain è una funzione WINAPI, ovvero rispetta la calling
convetion comune in tutte le API di windows, escluse alcune che ricevono un
numero di parametri variabile (per esempio wsprintf).
HINSTANCE hInst:
Si tratta dell'handle, del modulo del programma stesso (in poche parole il
file eseguibile);
HINSTANCE hPrevInstance:
Sempre con valore NULL in programmi win32, veniva usato in Win a 16
bit;
LPSTR lpCmdLine:
E' l'intera linea di comando passata al nostro programma (equivale ad
array argv[] del main nel C Standard). Non passa come stringa il nome
del programma;
int nCmdShow:
Questo valore può essere passato a ShowWindow();
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
L' handle, in poche parole, è un'identificatore univoco, che serve per identificare
un oggetto grafico (finestra, bottone, ...). Esso è un valore random che viene
generato dal sistema operativo ogni volta che l'applicativo entra in esecuzione.
In questo caso l' handle fa riferimento alla sessione di programma corrente, o
istanza.
hPrevInstance come ho già detto ha sempre valore NULL in windows a 32 bit. In
windows a 16 bit, invece, assumeva il valore dell'handle dell'istanza precedente,
ovviamente sempre se ne esisteva una.
Come in C Standard, lpCmdLine è un puntatore a stringhe di parametri passati
dopo il nome del programma stesso.
Ammettiamo di aver creato il programma argcommando.exe (salvato nella cartella
principale del C) . Semplicemente per passargli dei parametri, che verrano poi
utilizzati all'interno del programma stesso come fossero delle variabili, basta
richiamare il programma dal prompt MS-DOS nel seguente modo:
C:\> argcommando.exe
Da come si può ben vedere abbiamo solo dato come input la scritta per far aprire
il nostro programma.
Se vogliamo passare anche uno o più parametri dobbiamo semplicemente
aggiungerli accanto.
C:\> argcommando.exe 12 n
Nell'esempio sopra abbiamo passato due parametri, 12 (argv[1]) e n (argv[2]).
nCmdShow invece descrive il modo in cui la finestra deve essere visualizzata
quando viene eseguito l'applicazione.
Infine, come nello Standard C, anche in questo caso il programma finisce con un
return 0, ovvero restituendo un codice d'errore, per indicare che esso è
terminato.
In Questo paragrafo ho parlato spesso di C Standard, ma non ho ancora ben
spiegato chi si occupa di catalogare come standard funzioni e relativi header.
L'Organizzazione Internazionale per le Standardizzioni (ISO) è l'organismo che
definisce degli standard a livello mondiale in qualsiasi ambito, quindi non solo
quello informatico.
Esiste uno standard anche per i file immagine dei cd, chiamati per questo con
l'estensione di .iso, precisamente si tratta del filesystem standard ISO 9660.
Precedentemente il linguaggio C fu standardizzato dall'ANSI (American National
Standard Institute), il quale si mise in opera nell'estate del 1983, ci vollero circa
sei anni per terminare il progetto (Dicembre 1989).
Questa prima versione del C è chiamata C89 (derivante dall'anno), fino al 1999 il
quale venne adottata anche dall'ISO con il nome di C Standard ANSI/ISO o
C99.
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
2.1 MessageBox
La messageBox è la finestra più semplice che si possa creare con le API di
windows e proprio per questo motivo molti dei manuali e guide la trattano tra le
loro prime pagine. Essa è ben nota tra gli utilizzatori di un'ambiente grafico come
win, ma anche di altri come GNOME oppure KDE (ambienti opensource sviluppati
per i sistemi Linux).
E' intuitiva e semplice dal fatto che riceve pochi parametri in ingresso, tutto il
resto è dichiarato di default da windows stesso (colori, dimensione, cursore,...). In
poche parole si può dire che è una form già pronta, nulla quindi è più facile del suo
utilizzo.
Questo non significa però che in futuro sarete costretti ad utilizzarle per ogni
occasione che si presenta, anzi, dopo aver imparato a creare finestre grafiche 'non
pronte' potete costruirvi le vostre 'MessageBox personalizzate'.
Compatibilità:
•
Windows 95;
•
Windows 98;
•
Windows NT 3.1 o superiore;
•
Windows 2000;
•
Windows XP;
•
Windows CE 1.0 o superiore;
MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
hWnd
L'handle della MessageBox costruita.
IpText
Messaggio contenuto all'interno del form (o finestra).
IpCaption
Messaggio del titolo.
uType
Determina i vari stili (bottoni, icone, finestra) della MessageBox. Gli stili
disponibili sono presenti nelle quattro tabelle illustrate a seguito.
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Stile dei bottoni
Descrizione
MB_ABORTRETRYIGNORE
3 bottoni: Interrompi, Riprova, Ignora.
MB_DEFBUTTON1
Il primo pulsante si trova già selezionato.
MB_DEFBUTTON2
Il secondo pulsante si trova già selezionato.
MB_DEFBUTTON3
Il terzo pulsante si trova già selezionato.
MB_OK
1 bottone: Ok.
MB_OKCANCEL
2 bottoni: Ok, Annulla.
MB_RETRYCANCEL
2 bottoni: Riprova, Annulla.
MB_YESNO
2 bottoni: Si, No.
MB_YESNOCANCEL
3 bottoni: Si, No, Annulla.
MB_CANCELTRYCONTINUE
3 bottoni: Cancella, Prova, Continua. Disponibile solo in
Windows 2000.
MB_HELP
1 bottone: Help. Disponibile in Windows 95, 98, 2000,
XP e NT 4.0 o successivo. Questo pulsante non deve
stare da solo, ma accompagnato da almeno un altro.
Stile delle icone
Descrizione
MB_ICONASTERISK
MB_ICONINFORMATION
Icona con la lettera minuscola i.
MB_ICONERROR
MB_ICONHAND
MB_ICONSTOP
Include il segnale dello stop.
Generalmente utilizzato per mostrare errori.
MB_ICONEXCLAMATION
MB_ICONWARNING
Icona con un punto esclamativo.
MB_ICONQUESTION
Icona con il punto interrogativo.
Allineamento del testo
Descrizione
MB_RIGHT
Il testo viene allineato a destra.
MB_RTLREADING
Il titolo e i bottoni allineati a destra, il testo a sinistra.
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Stile della finestra
Descrizione
MB_APPLMODAL
L'utente deve rispondere alla finestra prima della
continuazione del lavoro nella finestra identificata dal
parametro del hWnd.
MB_SETFOREGROUND
La finestra assume priorità alta.
MB_TOPMOST
Genera la finestra di messaggio con lo stile della
finestra di WS_EX_TOPMOST.
Valori di ritorno
Nome
Descrizione
IDABORT
Interrompi è stato premuto.
IDCANCEL
Annulla è stato premuto.
IDCONTINUE
Continua è stato premuto.
IDIGNORE
Ignora è stato premuto.
IDOK
Ok è stato premuto.
IDYES
Si è stato premuto.
IDNO
No è stato premuto.
IDTRYAGAYN
Prova ancora è stato premuto.
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Nome
IDRETRY
Descrizione
Riprova è stato premuto.
Da come si può ben notare sotto nei due successivi esempi viene utilizzato il
carattere | , per intenderci quello accanto alla barra spaziatrice.
Esso serve per inserire più di uno stile, MB_YESNO e MB_ICONASTERISK nel
primo esempio, MB_OKCANCEL e MB_DEFBUTTON2 nel secondo.
ESEMPIO N.1
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int
nCmdShow) {
int mb_result; // variabile utilizzata per il ritorno di valore
mb_result = MessageBox(NULL, "Ti piace programmare?", "Domanda", MB_YESNO |
→ MB_ICONASTERISK);
→
if(mb_result == IDYES){
// istruzioni da far eseguire se viene premuto SI
}
else{
// istruzioni da far eseguire se viene premuto NO
}
return 0;
}
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Screen dell'esempio n.1
ESEMPIO N.2
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int
nCmdShow) {
int mb_result; // variabile utilizzata per il ritorno di valore
→
mb_result = MessageBox(NULL, "Desideri continuare?", "Domanda", MB_OKCANCEL |
MB_DEFBUTTON2);
→
if(mb_result == IDOK){
// istruzioni da far eseguire se viene premuto OK
}
else{
// istruzioni da far eseguire se viene premuto CANCEL
}
return 0;
}
Screen dell'esempio n.2
2.1.1 Utilizziamo la MessageBox
Finora l'unico elemento grafico che abbiamo trattato è la MessageBox, possiamo
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
quindi per ora, non avendo le conoscenze per preparare altri tipi di finestre,
utilizzarla in applicativi C Standard (in poche parole, quelli che eravate abituati a
scrivere).
Ovviamente i programmi devono comunque girare sotto Windows, visto che verrà
utilizzata la finestra di messaggio (MessageBox).
Facciamo come esempio un programma che ci permette di eseguire le operazioni
più elementari (somma, sottrazione, moltiplicazione, divisione e modulo).
Cerco di renderlo il più chiaro possibile, aggiungendoci del commenti dove ritenerò
più necessario.
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
ESEMPIO N.1
#include <windows.h>
#include <stdio.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int
nCmdShow) {
int mb_result; // variabile utilizzata per il ritorno di valore della MessageBox
float num1, num2, ris;
char operatore;
→
printf("Calcolatrice");
do{
printf("\n\nPrimo numero:\t");
scanf("%f", &num1);
fflush(stdin);
printf("Operatore:\t");
scanf("%c", &operatore);
fflush(stdin);
printf("Secondo numero:\t");
scanf("%f", &num2);
switch(operatore){ // controllo l'operando
case '+':
ris = num1 + num2;
break;
case '-':
ris = num1 - num2;
break;
case '*':
ris = num1 * num2;
break;
case '/':
ris = num1 / num2;
break;
case '%':
ris = int(num1) % int(num2);
break;
default:
MessageBox(NULL, "Operatore immeso non valido", "Secondo numero:\t", MB_OK |
→ MB_ICONERROR); // MessageBox di errore
ris = 0;
break;
}
printf("\nRisultato:\t%f", ris);
mb_result = MessageBox(NULL, "Vuoi rieseguire il programma?", "Domanda" , MB_YESNO |
→ MB_ICONQUESTION); // MesaBox per riavviare il programma
}
while(mb_result == IDYES); // se premuto YES riesegue il ciclo
return 0;
}
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
3.1.4 CreateHatchBrush
Anche con essa si possono colorare sfondi, anche se in modo diverso.
Infatti a differenza di CreateSolidBrush che lo riempiva completamente col colore
scelto, questa si limita a tracciare delle linee colorate.
Compatibilità:
•
Windows 95/98/2000/XP;
•
Windows NT 3.1 o superiore;
•
Windows CE 1.0 o superiore;
CreateHatchBrush(int fnStyle, COLORREF crColor);
fnStyle
Specifica la disposizione delle linee. Scegliere una delle flag qui sotto.
Hatch
Descrizione
HS_BDIAGONAL
Linee disposte diagonalmente da destra verso sinistra.
HS_CROSS
Disposizione sia verticale che orizzontale.
HS_DIAGCROSS
Diagonali da sinistra e da destra.
HS_FDIAGONAL
Linee disposte diagonalmente da sinistra verso destra.
HS_HORIZONTAL
Linee orizzontali.
HS_VERTICAL
Linee verticali.
crColor
Definiscee il colore delle linee. Si utilizza la Macro RGB.
Valori di ritorno
In caso di sucesso la funzione ritorna il valore del Brush creato. In caso contrario
ritorna NULL.
ESEMPIO N.1
[...]
wincl.hbrBackground = CreateHatchBrush(HS_CROSS, RGB(0, 255, 0) );
// linee orizzontali e verticali verdi
[...]
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Capitolo 4
“Una finestra già predefinita: il Dialogo”
Nel secondo capitolo di questo libro abbiamo già incontrato un tipo di finestra
predefinita: la MessageBox. Con essa è infatti possibile comunicare con l'utente
attraverso delle combinazioni di tasti specificati in opportune flag.
Ma se non siamo soddisfatti la libreria ci offre anche una finestra 'pronta', come
quella che abbiamo già creato nel capitolo precedente.
Il dialogo non è altro che una classe, una Window Class, già predefinita, ove
occorre attribuire solamente alcuni aspetti.
Questi aspetti vengono assegnati passando delle parole chiave in un foglio a parte,
alcune di esse già analizzate nel capitolo precedente.
Il file con il codice della dialog verra poi a congiungersi con quello principale
durante la compilazione se il vostro compilatore permette la creazione di un
Progetto (nel nostro caso Dev-C++ lo consente).
Tale foglio avrà estensione .rc (Resource Compiler) e può essere scritto anche con
l'utilizzo del Blocco Note di Windows, ma è sempre meglio l'uso di uno specifico
editor adatto alla creazione dei file di risorse. In questo caso siamo fortunati,
perché Dev-C++ ne dispone uno all'interno.
Sarà spiegato nel prossimo paragrafo la locazione dell'editor e i vari passi per la
compilazione del progetto.
I file risorse hanno una sintassi del tutto diversa da quella della programmazione
C. Infatti non si tratta di linguaggio di programmazione in questo caso ma di un
linguaggio di descrizione (dei dialoghi, ma anche di altre risorse, come le icone,
menù, cursori, ...).
4.1 Includiamo i resource nel nostro progetto
Vi sarete chiesti molto probabilmente come fare per far si che il file con la
descrizione dei dialoghi sia inclusa con il file contenente il WinMain.
Con Dev-C++, il nostro compilatore, occorre creare un Progetto, andando su
FILE-->Nuovo-->Progetto...
Fatto questo si sceglie l'icona Windows Application, si dà il nome al Progetto, si
sceglie il linguaggio (in questo caso il C) e infine si Salva il file del progetto.
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
Se aprite il progetto appena creato vi accorgerete che il nostro compilatore ha già
inserito una pagina contenente il WinMain ed il codice per una finestra.
Ovviamente potete cancellare il codice della finestra e sostituirlo con il vostro;
quello è solo un file inserito dal programma per facilitare i programmatori che per
la prima volta creano il loro progetto.
Nel caso in cui avete già creato il file WinMain basta semplicemente aggiungerlo al
progetto andando sul menù File-->Apri Progetto o File... e da qui selezionare la
pagina da inserire. E' inutile creare un progetto se l'eseguibile viene creato da un
solo file. Ma in questo ci servono almeno due pagine di codice, quella principale e
quella contenente la descrizione del dialogo o dialoghi nel caso ve ne fossero più di
uno.
Se invece ancora dovete creare una pagina WinMain ed il progetto è già salvato,
basta aprirlo e andare nel menù andare in File-->Nuovo-->File Sorgente (oppure
semplicemente premendo la combinazione di tasti Ctrl+N).
Quando occorre aggiungere il file di risorse invece aprite File-->Nuovo->File delle
risorse. In questo modo avrete la vostra pagina bianca .rc con l'editor che
riconosce le parole chiave presenti in tali file.
4.2 Descriviamo il nostro Dialogo
Inanzitutto occorre creare un File di risorse (la procedura è spiegata nel paragrafo
precedente).
Dovremo poi anche in questo caso includere l'header windows.h, dove al di sotto
inseriremo una o più descrizioni di dialoghi.
Vediamo un'esempio per capire meglio la sintassi di questi tipi di file.
#include <windows.h>
DialogoErrore DIALOG DISCARDABLE 0, 0, 186, 92
STYLE WS_POPUP | WS_SYSMENU
CAPTION "Errore!"
FONT 8, "MS Sans Serif"
BEGIN
END
Analizzerò nei paragrafi seguenti le keyword (le parole in grassetto) utilizzate per
la costruzione dei dialoghi.
4.2.1 Specifichiamo il Dialog
La prima riga di codice è quella che indica che si stà procedendo alla descrizione di
un dialogo (identificabile dal compilatore attraverso la parola chiave DIALOG).
E' stato aggiunto DISCARDABLE, ma è quasi meglio ometterlo, questo perchè
viene attivato di default.
DISCARDABLE significa che le risorse di tale elemento, vengono rimosse dalla
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
memoria se non vengono più utilizzate.
Analizziamo la sua sintassi per capire bene gli input che dobbiamo passare.
IdDialog DIALOG x, y, nWidth, nHeight
IdDialog
l'ID che identifica il nostro dialogo. Basta immettere un nome, il quale
sarà utilizzato nel programma per richiamare il resource della DialogBox.
int x, int y
Le cordinate dello schermo (gli assi x e y partono in alto a sinistra) per
l'angolo superiore sinistro della finestra.
Se utilizziamo il parametro CW_USEDEFAULT (o in x, o in y, o in tutti
due), la finestra sarà collocata in una posizione a caso della cordinata.
int nWidth, int nHeight
Questi altri due
in un'unità di
corrisponde ad
carattere (font)
interi indicano la dimensione della Dialog, non in pixel ma
misura detta DBU (Dialog Box Unit). Questa unita
un numero di pixel variabile a seconda del tipo di
utilizzato.
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
4.5.1 Stringa di testo
Stampare una stringa di testo in una dialog è molto semplice; L'unica difficoltà che
può venir a trovare il programmatore è quella del posizionamento dell'area nel
quale sarà poi inserito.
Occorre a volte fare diversi calcoli tra l'area della dialog e dell'elemento che lo
contiene (in questo caso del testo), per poter rendere il nostro applicativo il più
possibile gradevole esteticamente.
Ma questo è un problema che si incorre per ogni tipo di elemento.
CONTROL “text”, id, “STATIC”, style and ex-style, x, y, width, height
style and ex-style
Per il testo non esiste uno stile che lo identifica come per le icone o
immagini. Occorre inserire uno stile che ne determina il posizionamento
orizzontale (SS_LEFT, SS_CENTER, SS_RIGHT).
ESEMPIO N.1 (dialogs.rc)
#include <windows.h>
MyDialog DIALOG 50, 10, 300, 110
STYLE WS_SYSMENU | WS_BORDER // stili che si potevano omettere perchè di default
CAPTION "Dialog di esempio"
FONT 8, "verdana" // il font del testo che andremo ad inserire nella dialog
BEGIN
CONTROL "testo visualizzato al centro", 101, "STATIC", SS_CENTER, 0, 30, 300, 10
END
4.5.1-1 Identificatori per soli testi (LTEXT, CTEXT, RTEXT)
I programmatori delle librerie API Windows hanno ben deciso di permettere di
inserire stringhe di testo non solo utilizzando l'identificatore che abbiamo
precedentemente visto (CONTROL), il quale ci consente l'inserimento di una vasta
gamma di elementi, dai tipi static a quelli specifici per l'invio di messaggi, come i
pulsanti o form.
Ma esistono addirittura tre identificatori adatti solamente a questo scopo (stampa
di stringhe). Essi (LTEXT, CTEXT e RTEXT), sono identici tra di loro con la
differenza che hanno l'elemento stile di allineamento diverso. Con LTEXT potremo
scrivere una stringa posizionata a sinistra, CTEXT al centro e RTEXT a destra. Per
prova possiamo 'imbrogliare' il nostro compilatore inserendo uno stile non
coerente con l'identificatore. Ad esempio se immettiamo lo stile SS_CENTER a
LTEXT, il testo di risultato non sarà allineato a sinistra, ma al centro. Infatti il
compilatore in questo caso sostituisce lo stile di default (SS_LEFT) con quello da
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
noi inserito (SS_CENTER).
xTEXT "Text", id, x, y, width, height, [style and ex-style]
style and ex-style
Lo stile di allineamento orizzontale è già definito. Le parentesi quadre
stanno ad indicare che non è obbligatorio l'inserimento di uno o più stili.
ESEMPIO N.1 (dialogs.rc)
#include <windows.h>
MyDialog DIALOG 50, 10, 300, 110
STYLE WS_SYSMENU | WS_BORDER
CAPTION "Dialog di esempio"
FONT 8, "verdana"
BEGIN
CONTROL "testo visualizzato al centro", 101, "STATIC", SS_CENTER, 0, 30, 300, 10
END
4.5.2 Immagine
Un'altro elemento static è l'immagine bitmap, per capirci quella con estensione
.bmp .
Però, oltre a scrivere il controllo nel resource per la sua stampa, dovremo anche
definire il nome e percorso di essa.
nameId BITMAP “address”
nameId
address
Un nome, o numero, che identificherà poi tale immagine nei vari control
dei resource.
L'indirizzo del bitmap. Bisogna ricordarsi che per rappresentare un /
occorre scriverne due di seguito (se vi ricordate i caratteri non stampabili
del C). Per esempio se l'immagine ha indirizzo C:\\img1.bmp occorre
scrivere C:\\\\img1.bmp (tra virgolette).
NOTA: Consiglio di scrivere le definizioni di questo tipo in un file resource
differente da quello utilizzato per la dialog. In una futura lettura il codice in questo
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
modo sarà più leggibile e meno confusionario.
Ovviamente se lo inserite nello stesso resource dovrete fare attenzione ad inserirlo
al di fuori del contenuto della dialog.
Fatto questo non ci rimane che utilizzare l'identificatore CONTROL per permetterci
di stampare l'immagine che avevamo definito poco prima.
CONTROL “text”, id, “STATIC”, SS_BITMAP | style and ex-style, x, y, [width], [height]
text
In questo caso si tratta di immettere il nome che identifica la nostra
immagine, tra virgolette se si tratta di un nome alfanumerico, senza se si
tratta di un semplice numero.
style and ex-style
E' obbligatorio inserire lo stile SS_BITMAP (senza il compilatore non
riconosce che noi vogliamo la stampa di un bitmap). Si può inserire anche
SS_CENTERIMAGE,
SS_REALSIZECONTROL,
SS_REALSIZEIMAGE,
SS_RIGHTJUST.
NOTA: Se avete notato in questa situazione i parametri width e height sono
racchiusi tra parentesi quadre. Questo non significa che voi dovete inserirle nel
codice, ma stanno ad indicare che il valore (anche se bisogna attribuirne uno
obbligatoriamente) non è neccessario (in questo caso è meglio attribuire valori di
0), salvo con l'utilizzo di alcuni stili (come SS_CENTERIMAGE), nel quale sono
necessari.
ESEMPIO N.1 (dialogs.rc)
#include <windows.h>
MyDialog DIALOG 50, 10, 300, 110
STYLE WS_SYSMENU | WS_BORDER
CAPTION "Dialog di esempio"
FONT 8, "verdana"
BEGIN
CONTROL "LogoDlg", 300, "STATIC", SS_BITMAP|WS_BORDER, 30, 10, 0, 0
END
ESEMPIO N.1 (images.rc)
#include <windows.h>
LogoDlg BITMAP "C:\\\\logo.bmp"
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
4.6 Elementi Button
Si può immaginare già cosa possono essere questi tipo di controlli. Molti di voi,
infatti, avranno pensato immediatamente ai bottoni, e giustamente non hanno
sbagliato a rifersi proprio a costoro. Ma non esistono solamente i bottoni tipici, che
si trovano spesso nelle messagebox ed in quasi tutte le finestre. Ve ne sono anche
altri che permettono di comunicare in modo differente con l'applicativo.
Radiobutton, per esempio, consente di far segliere all'utente che esegue il
programma una sola opzione tra quelle in lista (i vari radiobutton appunto).
Un'altro controllo simile è il checkbox, questo si differisce dal precedente per la
possibilità di scelte anche muliple.
E' ovvio quindi che tali controlli sono dinamici per lavoro, non sarebbe possibile,
anche perchè inutile, renderli statici.
4.6.1 Pulsanti
La categoria dei pulsanti comprende tutti quelli che, precedentemente chiamati
con il termine di bottoni, permettono di dialogare con la finestra genitore nel
momento in cui l'utente clicca su di essi. Per farvi capire, quelli che abbiamo
incontrato nel paragrafo sulla MessageBox.
I pulsanti inviano, come tutti gli oggetti che vengono cliccati, il messaggio
WM_COMMAND. Naturalmente con la notifica STN_CLICKED.
CONTROL “text”, id, “BUTTON”, BS_PUSHBUTTON | style and ex-style, x, y, [width], [height]
style and ex-style
Si deve applicare lo stile BS_PUSHBUTTON per la creazione del nostro
pulsante. Nel caso velessimo far in modo che il bottone sia già
selezionato, lo stesso effetto che si otteneva aggiungendo lo stile
MB_DEFBUTTONx nella MessageBox, ci occorre aggiungere sostituirlo con
MB_DEFPUSHBUTTON.
Programmare l'interfaccia grafica in linguaggio C - Davide Giri
ESEMPIO N.1 (dialogs.rc)
#include <windows.h>
MyDialog DIALOG 50, 10, 180, 50
STYLE WS_SYSMENU | WS_BORDER
CAPTION "Dialog di esempio"
FONT 8, "verdana"
BEGIN
CONTROL "Sei sicuro di voler continuare?", 101, "STATIC", SS_CENTER, 0, 10, 180, 10
CONTROL "Ok", 401, "BUTTON", BS_PUSHBUTTON, 55, 30, 20, 12
CONTROL "Anulla", 402, "BUTTON", BS_DEFPUSHBUTTON, 85, 30, 40, 12
END
4.6.1-1 Identificatori per soli pulsanti
Pure questa volta si può scegliere la via più facile, utilizzando un commando
dedicato all'inserimento di pulsanti.
Anzi, per la precisione, ne esistono ben due: PUSHBUTTON e DEFPUSHBUTTON.
Il primo (PUSHBUTTON) vale come CONTROL con lo stile BS_PUSHBUTTON, il
secondo
(DEFPUSHBUTTON)
ovviamente
corrisponde
con
l'altro
stile,
BS_DEFPUSHBUTTON.
PUSHBUTTON "Text", id, x, y, width, height, [style and ex-style]
DEFPUSHBUTTON "Text", id, x, y, width, height, [style and ex-style]
style and ex-style
Già definito di default lo stile BS_PUSHBUTTON nel commando
PUSHBUTTON, lo stile BS_DEFPUSHBUTTON in DEFPUSHBUTTON.
ESEMPIO N.1 (dialogs.rc)
#include <windows.h>
MyDialog DIALOG 50, 10, 180, 50
STYLE WS_SYSMENU | WS_BORDER
CAPTION "Dialog di esempio"
FONT 8, "verdana"
BEGIN
CONTROL "Sei sicuro di voler continuare?", 101, "STATIC", SS_CENTER, 0, 10, 180, 10
PUSHBUTTON "Ok", 401, 55, 30, 20, 12
DEFPUSHBUTTON "Anulla", 402, 85, 30, 40, 12
END