Realizzazione di una Finestra con le API Windows
3 Ottobre 2007 Programmazione
   





Una Semplice Finestra

Per costruire una semplice finestra si crea una Win32 Application nel modo visto in precedenza e si scrive il seguente programma

simplewin.c
  1. #include <windows.h>
  2.  
  3. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  4. {
  5. switch(msg)
  6. {
  7. case WM_CLOSE: DestroyWindow(hwnd); break;
  8. case WM_DESTROY: PostQuitMessage(0); break;
  9. default: return DefWindowProc(hwnd, msg, wParam, lParam);
  10. }
  11. return 0;
  12. }
  13.  
  14. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  15. LPSTR lpCmdLine, int nCmdShow)
  16. {
  17. WNDCLASSEX wc;
  18. HWND handle;
  19. MSG message;
  20.  
  21. //Registrazione della Window Class
  22. wc.cbSize = sizeof(WNDCLASSEX);
  23. wc.style = 0;
  24. wc.lpfnWndProc = WndProc;
  25. wc.cbClsExtra = 0;
  26. wc.cbWndExtra = 0;
  27. wc.hInstance = hInstance;
  28. wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  29. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  30. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  31. wc.lpszMenuName = NULL;
  32. wc.lpszClassName = "simplewin";
  33. wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  34.  
  35. if(!RegisterClassEx(&wc))
  36. {
  37. MessageBox(NULL, "Registrazione della Finestra Fallita!", "Errore!",
  38. MB_ICONEXCLAMATION | MB_OK);
  39. return 0;
  40. }
  41.  
  42. // Creazione della finestra
  43. // Una volta registrata la classe si passa a costruire la finestra.
  44. handle = CreateWindowEx(WS_EX_CLIENTEDGE, "simplewin",
  45. "Titolo della mia finestra", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
  46. CW_USEDEFAULT, 340, 120,NULL, NULL, hInstance, NULL);
  47.  
  48. // si verifica se la finestra è stata creata verificando se l'handle è valido
  49. if(handle == NULL)
  50. {
  51. MessageBox(NULL, "Creazione della Finestra Fallita!", "Errore!",
  52. MB_ICONEXCLAMATION | MB_OK);
  53. return 0;
  54. }
  55.  
  56. ShowWindow(handle, nCmdShow); // Si visualizza la finestra
  57. UpdateWindow(handle); // si aggiorna la finestra
  58.  
  59. // Ci si pone in ascolto dei messaggi verso la finestra
  60. while(GetMessage(&message, NULL, 0, 0) > 0)
  61. {
  62. TranslateMessage(&message);
  63. DispatchMessage(&message);
  64. }
  65.  
  66. return message.wParam; // exit value restituito al sistema
  67. }
 
La finestra prodotta è la seguente

Figura 6. Una Semplice Finestra.
La costruzione di questa finestra avviene nei seguenti passi
  • si definiscono tre variabili
    • la variabile wc di tipo WNDCLASSEX, che conterrà delle informazioni sulla finestra che si vuole costruire;
    • la variabile handle di tipo HWND (Window Handle), che conterrà l’handle della finestra che si vuole costruire;
    • la variabile message di tipo MSG;


    1. WNDCLASSEX wc;
    2. HWND handle;
    3. MSG message;

  • si definiscono le proprietà della finestra fissando i campi della variabile wc

    1. wc.cbSize = sizeof(WNDCLASSEX);
    2. wc.style = 0;
    3. wc.lpfnWndProc = WndProc;
    4. wc.cbClsExtra = 0;
    5. wc.cbWndExtra = 0;
    6. wc.hInstance = hInstance;
    7. wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    8. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    9. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    10. wc.lpszMenuName = NULL;
    11. wc.lpszClassName = "simplewin";
    12. wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

  • una volta definita la finestra la si deve registrare. Questo si fa tramite l’istruzione RegisterClassEx

    1. if(!RegisterClassEx(&wc))
    2. {
    3. MessageBox(NULL, "Registrazione della Finestra Fallita!", "Errore!",
    4. MB_ICONEXCLAMATION | MB_OK);
    5. return 0;
    6. }

  • viene creata la finestra tramite l’istruzione CreateWindowEx

    1. handle = CreateWindowEx(WS_EX_CLIENTEDGE, "simplewin",
    2. "Titolo della mia finestra", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
    3. CW_USEDEFAULT, 340, 120,NULL, NULL, hInstance, NULL);

  • si verifica se la finestra è stata creata verificando se l’handle è valido

    1. if(handle == NULL)
    2. {
    3. MessageBox(NULL, "Creazione della Finestra Fallita!", "Errore!",
    4. MB_ICONEXCLAMATION | MB_OK);
    5. return 0;
    6. }

  • si visualizza la finestra tramite l’istruzione ShowWindow, e la si ridisegna tramite l’istruzione UpdateWindow

    1. ShowWindow(handle, nCmdShow); // Si visualizza la finestra
    2. UpdateWindow(handle); // si aggiorna la finestra

  • si entra in un ciclo in cui si accettano tutti i messaggi diretti alla finestra e li si invia alla funzione WndProc che li processerà

    1. while(GetMessage(&message, NULL, 0, 0) > 0)
    2. {
    3. TranslateMessage(&message);
    4. DispatchMessage(&message);
    5. }

    tramite la funzione GetMessage ci si pone in ascolto e in attesa di un messaggio inviato verso la finestra. Non appena arriva un messaggio questo viene tradotto tramite la funzione TranslateMessage (il segnale che arriva, dal sistema operativo, viene tradotto in un valore che consentirà poi alla procedura WndProc di processarli). Il messaggio tradotto viene passato, tramite l'istruzione DispatchMessage, alla funzione WndProc che provvederà a processarlo.
    Il programma resterà in ascolto, tramite la funzione GetMessage, fino a quando non si verificherà un errore, nel qual caso la GetMessage restituirà il valore -1, o fino a quando non sarà prelevato dalla coda dei messaggi il messaggio WM_QUIT, nel qual caso la GetMessage restituirà il valore 0.
    Quindi finché il valore restituito dalla GetMessage sarà maggiore di zero il programma resterà in ascolto.
  • si definisce la funzione WndProc che si occuperà di processare tutti i messaggi in arrivo per la finestra.

    1. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    2. {
    3. switch(msg)
    4. {
    5. case WM_CLOSE: DestroyWindow(hwnd); break;
    6. case WM_DESTROY: PostQuitMessage(0); break;
    7. default: return DefWindowProc(hwnd, msg, wParam, lParam);
    8. }
    9. return 0;
    10. }

    La funzione riceve i messaggi inviati da DispatchMessage e li processa. La funzione è definibile dall'utente che potrà decidere il comportamento da seguire in corrispondenza ai vari possibili messaggi che si possono ricevere.
    Nell'esempio qui proposto la funzione riceve il messaggio msg, quindi se il messaggio è WM_CLOSE (è stato premuto il close button) la finestra viene chiusa invocando la funzione DestroyWindow passandogli come parametro l'handle della finestra, se il messaggio è WM_DESTROY (la finestra è stata chiusa) viene specificato l'exit code dell'applicazione invocando la funzione PostQuitMessage.
    In caso arrivi un qualsiasi altro messaggio viene richiamata la funzione DefWindowProc a cui vengono passati gli stessi parametri della funzione WndProc.

La funzione GetMessage restituisce un messaggio ottenuto dalla coda dei messaggi del thread. Invia i messaggi in arrivo fino a quando vi sono messaggi disponibili nella coda.

  1. BOOL GetMessage(
  2. LPMSG lpMsg,
  3. HWND hWnd,
  4. UINT wMsgFilterMin,
  5. UINT wMsgFilterMax
  6. );

Se dalla coda dei messaggi viene estratto un messaggio diverso da WM_QUIT viene restituito un valore diverso da zero, altrimenti viene restituito zero. Se si verifica un errore viene restituito -1.

lpMsg [out] Puntatore ad una struttura MSG in cui si metterà il messaggio prelevato dalla coda dei messaggi del thread.
hWnd [in] Handle della finestra a cui andranno inviati i messaggi. La finestra deve appartenere al thread corrente. Se hWnd è NULL il messaggio viene inviato a tutte le finestre che appartengono al thread corrente. Se hWnd è -1 restituisce solo i messaggi presenti nella coda il cui valore hnwd è NULL.
wMsgFilterMin [in] Specifica l'indice del primo messaggio da restituire. Se wMsgFilterMin e wMsgFilterMax sono entrambi zero, GetMessage restituisce tutti i messaggi disponibili.
wMsgFilterMax [in] Specifica l'indice dell'ultimo messaggio da restituire. Se wMsgFilterMin e wMsgFilterMax sono entrambi zero, GetMessage restituisce tutti i messaggi disponibili.

La funzione TranslateMessage traduce il messaggio costituito da parole chiave (ad es. WM_KEYDOWN, WM_KEYUP, WM_CLOSE, WM_DESTROY, ecc.) in un messaggio costituito da caratteri. Ogni parola chiave viene tradotta in una stringa di caratteri che la identifica, così, ad esempio, quando viene passato a TranslateMessage il messaggio costituito dalla parola chiave WM_CLOSE questo viene tradotto nella stringa di caratteri "WM_CLOSE".

  1. BOOL TranslateMessage(
  2. const MSG *lpMsg
  3. );

La funzione traduce il messaggio lpMsg sovrascrivendo lpMsg (il messaggio tradotto è sovrascritto al messaggio iniziale). lpMsg è un puntatore ad una struttura MSG che conterrà il messaggio ottenuto dalla coda dei messaggi del thread. Se il messaggio viene tradotto viene restituito un valore diverso da zero. Se il messaggio non viene tradotto (non vi sono messaggi nella coda dei messaggi del thread) viene restituito zero.

La funzione DispatchMessage invia un messaggio alla window procedure (WndProc). è usata tipicamente per inviare i messaggi ottenuti dalla funzione GetMessage

  1. LRESULT DispatchMessage(
  2. const MSG *lpmsg
  3. );

Il valore restituito è il valore restituito dalla funzione WndProc.

La funzione DestroyWindow

  1. BOOL DestroyWindow(HWND hWnd);

distrugge la finestra il cui handle è hWnd. La funzione invia il messaggio WM_DESTROY alla finestra, la funzione distrugge anche il menù della finestra, svuota la coda di messaggi del thread, ecc. Distrugge automaticamente anche eventuali finestre figlie.
Se la funzione ha successo restituisce un valore diverso da zero, se non ha successo restituisce zero.

La funzione PostQuitMessage

  1. void PostQuitMessage(int nExitCode);

indica al sistema che un thread ha chiesto di terminare l'esecuzione. È tipicamente utilizzata in risposta alla ricezione del messaggio WM_DESTROY. Il parametro nExitCode specifica l'exit code dell'applicazione.
La funzione invia il messaggio WM_QUIT alla coda di messaggi del thread e termina. Quando il thread preleva il messaggio WM_QUIT dalla sua coda dei messaggi restituisce il controllo al sistema. L'exit value restituito al sistema è il parametro wParam del messaggio WM_QUIT.

La struttura WNDCLASSEX contiene informazioni sulla finestra. è usata dalle funzioni RegisterClassEx e GetClassInfoEx. è definita come

  1. typedef struct {
  2. UINT cbSize;
  3. UINT style;
  4. WNDPROC lpfnWndProc;
  5. int cbClsExtra;
  6. int cbWndExtra;
  7. HINSTANCE hInstance;
  8. HICON hIcon;
  9. HCURSOR hCursor;
  10. HBRUSH hbrBackground;
  11. LPCTSTR lpszMenuName;
  12. LPCTSTR lpszClassName;
  13. HICON hIconSm;
  14. } WNDCLASSEX, *PWNDCLASSEX;

dove

cbSize Indica la dimensione in bytes della struttura che conterrà tutte le informazioni sulla finestra. Fissare tale valore a sizeof(WNDCLASSEX)
style Indica lo stile della classe. È possibile combinare più stili.
lpfnWndProc Conterrà il puntatore alla funzione (WndProc) che processerà i messaggi passati dal sistema operativo alla finestra;
cbClsExtra Quantità di memoria extra da allocare per la classe. Il sistema inizializza questo valore a zero.
cbWndExtra Quantità di memoria (in byte) allocata per i dati extra da passare alle finestre create sulla base di questa classe. In genere è 0
hInstance Handle dell’istanza di questo programma. Viene passata come parametro a WinMain. È fornita dal sistema operativo all’atto della creazione dell’istanza
hIcon Handle dell'icona della classe. Se è pari a NULL il sistema fornisce una icona di default
hCursor Handle del cursore della classe Se è pari a NULL una applicazione si occuperà di disegnare il cursore quando passa sulla finestra
hbrBackground Handle del Brush di Background della classe per settare il colore di sfondo della finestra
lpszMenuName Puntatore ad una stringa che indica il nome della risorsa del menù della finestra
lpszClassName Indica il nome della classe, ovvero quello che utilizzeremo per creare la finestra con CreateWindowEx
hIconSm Handle di una icona piccola associata alla classe.

La funzione CreateWindowEx è definita come

  1. HWND CreateWindowEx(
  2. DWORD dwExStyle,
  3. LPCTSTR lpClassName,
  4. LPCTSTR lpWindowName,
  5. DWORD dwStyle,
  6. int x,
  7. int y,
  8. int nWidth,
  9. int nHeight,
  10. HWND hWndParent,
  11. HMENU hMenu,
  12. HINSTANCE hInstance,
  13. LPVOID lpParam
  14. );

i cui parametri sono

dwExStyle Specifica lo stile della finestra appena creata. Se non si vogliono stili particolari si fissa NULL
lpClassName Il nome della classe che si vuole creare.
lpWindowName Puntatore ad una stringa che contiene il nome della finestra
dwStyle Specifica lo stile della finestra appena creata. Questo parametro può essere una combinazione di stili
x Specifica la posizione orizzontale iniziale della finestra
y Specifica la posizione verticale iniziale della finestra
nWidth La larghezza iniziale della finestra
nHeight L’altezza iniziale della finestra
hWndParent L’handle della finestra genitore, ovvero quella che conterrà la finestra che noi vogliamo creare. Se si crea una finestra di dialogo il genitore sarà il desktop, in tal caso sarà sufficiente settarlo a NULL. È un parametro opzionale per le finestre di pop-up
hMenu L’handle dell’eventuale menu che vorremo inserire nella nostra finestra. Se non vogliamo mettere menu, deve essere NULL
hInstance È l'istanza del modulo associato alla finestra
lpParam Puntatore ad un valore da passare alla finestra attraverso la struttura di CREATESTRUCT

La funzione ShowWindow è definita come

  1. BOOL ShowWindow(
  2. HWND hWnd,
  3. int nCmdShow
  4. );

i cui parametri sono hWnd, che è l'handle della finestra, e nCmdShow che specifica come la finestra deve essere visualizzata. La prima volta che viene chiamata all'interno della WinMain riceve il valore dal parametro nCmdShow della WinMain. Nelle chiamate seguenti questo parametro può assumere i seguenti valori, alcuni descritti in precedenza: SW_FORCEMINIMIZE, SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOW, SW_SHOWDEFAULT, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE, SW_SHOWNA, SW_SHOWNOACTIVATE, SW_SHOWNORMAL.

SW_FORCEMINIMIZE Minimizza la finestra se il thread che la gestisce non risponde.
SW_SHOWDEFAULT Attiva la finestra e la visualizza nella sua posizione e dimensione corrente.

Se la finestra era visibile restituirà un valore diverso da zero, se la finestra era nascosta restituirà zero.
Pagina 2 di 5
Prec 1 2 3 4 5 Succ