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