Realizzazione di una Finestra con le API Windows
Mer 03 Ott 2007
   





Inserimento di un Menù

Nell'esempio proposto si costruisce il menù utilizzando il resource builder di Visual C++, esistono tuttavia anche altri resource builder che possono essere utilizzati.
Il resource builder produrrà, a partire dal menù creato dall'utente, due file: il file resource.h e un file con estensione rc. Per il menù creato nell'esempio il resource builder produce i due file resource.h e script2.rc.
All'interno del file .rc il resource builder salverà le indicazioni sulla costituzione della finestra. Ad esempio i vari componenti della finestra e la loro esatta disposizione all'interno della finestra.
Quando si compilerà il programma e si produrrà il relativo file eseguibile (.exe) saranno inserite, da parte del compilatore, le istruzioni per la costruzione della finestra secondo quanto definito all'interno del file resource.  

Il file resource.h per il menù creato nell'esempio è il seguente

resource.h
  1. //{{NO_DEPENDENCIES}}
  2. // Microsoft Developer Studio generated include file.
  3. // Used by Script2.rc
  4. //
  5.  
  6. #define IDR_MENU1 101
  7. #define ID_FILE_OPEN 40001
  8. #define ID_FILE_SAVE 40002
  9. #define ID_INFO_ABOUT 40003
  10.  
  11. // Next default values for new objects
  12. //
  13. #ifdef APSTUDIO_INVOKED
  14. #ifndef APSTUDIO_READONLY_SYMBOLS
  15. #define _APS_NEXT_RESOURCE_VALUE 102
  16. #define _APS_NEXT_COMMAND_VALUE 40004
  17. #define _APS_NEXT_CONTROL_VALUE 1000
  18. #define _APS_NEXT_SYMED_VALUE 101
  19. #endif
  20. #endif

Una volta costruito il menù e prodotto il file resource.h si può andare nel programma principale ed utilizzare i componenti creati. Per utilizzare i componenti si procede nel seguente modo.
Innanzitutto una volta prodotti i file resource.h e script2.rc bisogna aggiungerli al progetto. Per farlo si va sul menù Project di visual studio, quindi su Add to Project - Files

Figura 7. Add to Project.

Una volta aggiunti i file al progetto si apportano le seguenti modifiche al programma
  • si include il file resource.h

    1. #include "resource.h"

  • si indica che la finestra ha un menù modificando il campo lpszMenuName della variabile wc

    1. wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);

    la macro MAKEINTRESOURCE converte un valore intero in un tipo risorsa compatibile con le funzioni di gestione delle risorse. Questa macro è utilizzata invece di inserire la stringa con il nome della risorsa. IDR_MENU1 è la stringa con cui si identifica il menù che è stato definito con il resource builder.
    Con questa assegnazione si indica che la finestra ha un menù e questo menù è quello che è definito all'interno del file resource script2.rc ed è identificato da IDR_MENU1.
La nuova finestra con il menù è la seguente

Figura 8. Finestra con menù.

Si noti che se si seleziona un qualsiasi elemento del menù non succede nulla, ovvero in corrispondenza alla selezione di una voce del menù non si produce alcun effetto. Questo perché non si è ancora inserito il codice per la gestione del menù.
Ogni volta che l'utente seleziona una voce del menù di una finestra viene inviato il messaggio WM_COMMAND (codice del messaggio) a quella finestra (ovvero alla procedura che controlla quella finestra). Il messaggio viene catturato dalla funzione GetMessage all'interno della funzione WinMain relativa a quella finestra e viene inviato alla funzione WndProc per essere processato.
All'interno della funzione WndProc si prenderanno in considerazione tutti i comandi inviati alla finestra. La funzione sarà fondamentalmente costituita da una switch in cui ogni elemento della switch sarà un possibile comando inviato alla finestra. Per ogni comando vi saranno delle istruzioni da eseguire, le istruzioni potranno trovarsi interamente all'interno della switch oppure potranno essere all'interno di una funzione che sarà chiamata all'interno della switch in corrispondenza al comando.

  1. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  2. {
  3. switch(msg)
  4. {
  5. case WM_COMMAND:
  6. switch(LOWORD(wParam))
  7. {
  8. case ID_FILE_OPEN: // il tasto sinistro del mouse è stato
  9. // premuto in corrispondenza dell'elemento Open del
  10. // menu File
  11. break;
  12. case ID_FILE_SAVE:
  13. // il tasto sinistro del mouse è stato premuto
  14. // in corrispondenza dell'elemento Save del
  15. // menu File
  16. break;
  17. case ID_INFO_ABOUT:
  18. break;
  19. }
  20. break;
  21. case WM_CLOSE: DestroyWindow(hwnd); break;
  22. case WM_DESTROY: PostQuitMessage(0); break;
  23. default: return DefWindowProc(hwnd, msg, wParam, lParam);
  24. }
  25. return 0;
  26. }

Nel caso in cui il comando per la finestra sia relativo alla selezione di un elemento del menù, sarà inviato alla finestra il messaggio WM_COMMAND. Ora, dal momento che i possibili comandi derivanti dal menù sono più di uno dovrà esservi una ulteriore switch questa volta all'interno del blocco relativo a WM_COMMAND.
Per individuare quale dei vari item del menù è stato selezionato si utilizza il parametro wParam, parametro a 32 bit in cui HIWORD(wParam), 16 bit, indica il codice di notifica e LOWORD(wParam), 16 bit, conterrà l'identificatore dell'elemento selezionato così come definito in script2.rc.
Quando l'utente seleziona un item di un menù viene inviato il messaggio WM_COMMAND

  1. WM_COMMAND
  2. WPARAM wParam;
  3. LPARAM lParam;

dove wParam (high word), 16 bit, sarà pari a 0 e in wParam (low word) vi sarà il codice che identifica l'item del menù selezionato. Il codice sarà quello specificato, per quell'item, nel file con estensione .rc.
Se nel menù è presente un separatore e viene selezionato dall'utente il sistema invia il messaggio WM_COMMAND con anche wParam (low word) pari a 0.

Il programma completo è il seguente.

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

Pagina 3 di 5
Prec 1 2 3 4 5 Succ