LEKCJA 45: Do��czanie zasob�w - menu i okienka dialogowe. ________________________________________________________________ Jak doda� menu i okienka dialogowe do aplikacji. ________________________________________________________________ Aby doda� do aplikacji menu nale�y utworzy� plik (ASCII) zasob�w *.RC, kt�ry zostanie u�yty w projekcie. Pierwsz� instrukcj� jest MENU, "NazwaMenu", MENU i para s��w kluczowych (znanych z Pascala) BEGIN oraz END, mi�dzy kt�rymi znajdzie si� kombinacja instrukcji MENUITEM oraz POPUP. MENUITEM definiuje pozycj� na g��wnym pasku menu - okre�la - jak b�dzie wygl�da� i jaki identyfikator b�dzie j� reprezentowa�. Instrukcja POPUP pozwala, rozwin�� list� pozycji wchodz�cych w sk�ad danego menu. Nazwa menu mo�e by� u�yta podczas rejestracji klasy danego okna jako wpisana w odpowiednie pole struktury na kt�rej oparte jest okno. W ten spos�b uzyskamy menu dla wszystkich okien danej klasy. BEGIN POPUP "Rozkaz" BEGIN MENUITEM "Rozkaz 1", IDM_R1 MENUITEM "Rozkaz 2", IDM_R2 MENUITEM "Rozkaz 3", IDM_R3 END POPUP "Kolor" BEGIN MENUITEM "Czarny", IDM_BLACK MENUITEM "Niebieski", IDM_BLUE MENUITEM "Zielony", IDM_GREEN END MENUITEM "Koniec", IDM_EXIT END Ka�da pozycja ma w�asny identyfikator, np. IDM_EXIT, IDM_BLUE, kt�ry Windows przekazuj� do aplikacji, gdy zostaje ona wybrana przez u�ytkownika z systemu menu. Poniewa� ka�dy identyfikator powinien by� unikalny, najlepiej jest go zdefiniowa� w pliku zasob�w .RC lub w�asnym pliku nag��wkowym .H: #define IDM_EXIT 100 #define IDM_BLUE 101 #define IDM_R1 102 ... Mamy ju� zdefiniowane menu w pliku zasob�w, nale�y je teraz do��czy� do aplikacji na jeden z dw�ch sposob�w: - Mo�na okre�li� menu jako menu danej klasy okien, gdy klasa ta jest rejestrowana. W ten spos�b do��czymy menu do ka�dego okna opartego na tej klasie. Aby to wykona�, wystarczy przypisa� odpowiedniemu polu struktury nazw� naszego menu. Je�eli obiekt klasy WNDCLASS nazwiemy Window1, to: Window1.lpszMenuName = "NazwaMenu"; Gdy klasa zostanie zarejestrowana, ka�de okno tej klasy b�dzie mia�o to samo menu, chyba �e dostarczymy odpowiedni identyfikator menu w momencie tworzenia okna funkcj� CreateWindow(). - Drugim sposobem jest do��czenie menu w momencie tworzenia okna, wtedy tylko tworzone okno b�dzie mia�o dane menu. Nale�y najpierw za�adowa� menu przy u�yciu funkcji LoadMenu(), kt�ra zwraca jego identyfikator: HMENU hMenu = LoadMenu(hInstance, "NazwaMenu"); hWnd = CreateWindow(szAppName, "Nazwa Aplikacji", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, hMenu, <-- tu hIstance, NULL ); Typow� praktyk� jest do��czenie pozycji menu do instrukcji switch w funkcji okienkowej. Poniewa� Windows wysy�a komunikat WM_COMMAND do odpowiedniej funkcji okienkowej w odpowiedzi na wyb�r pozycji przez u�ytkownika, a parametr wParam zawiera identyfikator tej�e pozycji - mo�na napisa� tak: case WM_COMMAND: switch (wParam) { case IDM_R1: ... obs�uga ...; break; case IDM_R2: ... obs�uga ...; break case IDM_QUIT: ...DestroyWindow(...); } Jak rozbudowuje si� menu. API Windows zawiera funkcje, umo�liwiaj�ce rozbudow� menu nawet w ruchu aplikacji (run-time). Rozbudowa menu w konkretnym oknie nie poci�ga za sob� zmian w innych, opartych na tej samej klasie oknach. Jest to mo�liwe, poniewa� w chwili tworzenia okna otrzymuje ono swoj� kopi� menu (tradycyjne w C/C++ przekazywanie kopii zmiennej do funkcji). Nie wszystkie pozycje w menu s� w danym stadium pracy aplikacji sensowne (mo�liwe do wykonania). Zaraz przekonasz si�, jak to si� dzieje, �e niekt�re pozycje "robi si� na szaro". W API Windows s�u�y do tego funkcja: EnableMenuItem (hMenu, IDM_R1, MF_DISABLED); EnableMenuItem (hMenu, IDM_R1, MF_GRAYED); EnableMenuItem (hMenu, IDM_R1, MF_ENABLED); Rozkaz R1 skojarzony z identyfikatorem IDM_R1 i znajduj�cy si� w systemie menu o oznaczniku hMenu stanie si� kolejno zablokowany, widoczny-lecz-niedost�pny, dost�pny. Dodawanie i usuwanie pozycji w menu Dodawanie pozycji do menu mo�e by� wykonane dwoma sposobami: przez wstawienie pomi�dzy istniej�ce pozycje lub na ko�cu listy. W pierwszym przypadku nale�y u�y� funkcji InsertMenu(). Funkcja ta pozwala jednocze�nie okre�li� status pozycji, mi�dzy innymi czy b�dzie umieszczone nowe pole mo�na okre�li� dwoma sposobami: przez identyfikator pozycji maj�cej by� przed now� lub przez numeracj� poszczeg�lnych, licz�c id lewej skrajnej pozycji (C++ tradycyjnie liczy od zera). Spos�b "odliczania" pozycji w systemie menu okre�la tryb (BYCOMMAND lub BYPOSITION - rozkaz, b�d� pozycja): InsertMenu(hMenu, IDM_R1, MF_BYCOMMAND |MF_DISABLED, IDM_R5, "Rozkaz 5"); InsertMenu(hMenu, 1, MF_ENABLED, IDM_R5, "Rozkaz 5"); Funkcja wstawi za pozycj� "Rozkaz 1" now� pozycj� "Rozkaz 5", jednocze�nie ustawia jej status. Drug� funkcj� dodaj�c� pozycj� do utworzonego systemu menu jest: AppendMenu(hMenu, MF_ENABLED, IDM_R4, "Rozkaz 4"); Poni�ej przyk�ad zdefiniowania menu aplikacji w taki w�a�nie spos�b: case WM_CREATE: hMenu = CreateMenu(); //Utworzenie menu AppendMenu(hMenu, MF_ENABLED, IDM_R1, "Rozkaz 1"); AppendMenu(hMenu, MF_ENABLED, IDM_R2, "Rozkaz 2"); AppendMenu(hMenu, MF_ENABLED, IDM_R3, "Rozkaz 3"); SetMenu(hWnd, hMenu); //Wy�wietlenie menu ... break; Usuwanie pozycji z menu mo�na przeprowadzi� dwoma sposobami: - poprzez wskazanie numeru pozycji w systemie menu: DeleteMenu(hMenu, 1, MF_BYPOSITION); //usuni�ta zostanie druga //pozycja z systemu menu - przez wyszczeg�lnienie identyfikatorem pozycji DeleteMenu(hMenu, IDM_R3, MF_BYCOMMAND); Po usuni�ciu pozycji z menu Window usunie r�wnie� wszystkie zwi�zane z ni� submenu. Zaznaczanie pozycji w menu (mark). Obok pozycji w menu mo�na umie�ci� znak markuj�cy ("ptaszek"). Znak markuj�cy mo�na zainicjowa� w pliku zasob�w .RC. Dzi�ki temu, u�ytkownik w momencie otwarcia okna dowie si� z wygl�du menu o pocz�tkowym ustawieniu opcji. MENUITEM "Rozkaz 2", IDM_R2, CHECKED W trakcie pracy aplikacji nale�y pos�u�y� si� funkcj� CheckMenuItem(). Zwykle najpierw kasujemy "ptaszka" przy poprzedniej pozycji: CheckMenuItem( hMenu, IDM_R2, MF_UNCHECKED); CheckMenuItem(hMenu, IDM_R3, MF_CHECKED); Zmiany pozycji menu Funkcja ModyfyMenu() pozwala na zmian� nazwy pozycji i jej atrybut�w. Oto przyk�ady u�ycia tej funkcji: ModifyMenu(hMenu, IDM_R2, MF_BYCOMMAND, IDM_R2, "Polecenie 2"); Identyfikator pozycji nie ulegnie zmianie, jedynie nazwa pola z "Rozkaz 2" na "Polecenie 2". Mo�emy zmieni� jednocze�nie i identyfikator, by nie pomyli� si� w programie: ModifyMenu(hMenu, IDM_R2, MF_BYCOMMAND, IDM_P2, "Polecenie 2"); Dodatkowo mo�na ustawi� za jednym zamachem i atrybuty: ModifyMenu(hMenu, IDM_R2, MF_BYCOMMAND | MF_CHECKED | MF_GRAYED, IDM_R2, "Polecenie 2"); U�ycie grafiki w systemie menu. W systemie menu aplikacji mo�emy zamiast �a�cucha znak�w "Rozkaz 2" umie�ci� element graficzny - np. w postaci mapy bitowej. Zamiast pola o nazwie "Pole", wprowadza map� bitow�: HMENU hMenu = GetMenu(hWnd); HBITMAP hBitmap = LoadBitmap (hIstance, "Pole"); ModifyMenu(hMenu, IDM_R2, MF_BYCOMMAND | MF_BITMAP, IDM_R2, (LPSTR) MAKELONG (hBitmap, 0)); GetMenu() zwraca oznacznik aktualnego menu, potrzebny jako pierwszy parametr funkcji ModifyMenu(). Drugim parametrem tej funkcji jest identyfikator pozycji, kt�r� chcemy zmieni�. Trzecia okre�la, �e zmiana ma by� wykonana przez wyszukanie pozycji za po�rednictwem jej identyfikatora oraz �e now� pozycj� ma reprezentowa� mapa bitowa. Czwarty parametr okre�la identyfikator nowej pozycji. Poniewa� ostatnim parametrem nie jest ju� wska�nik do �a�cucha znakowego, nale�y przes�a� oznacznik mapy bitowej jako mniej znacz�ce s�owo tego parametru. W tym celu 16-bitowy oznacznik jest ��czony z 16-bitow� sta��, a nast�pnie poddawany konwersji do typu Long Pointer to STRing. Zmiana menu aplikacji na kolejne. Aplikacja w r�nych stadiach pracy mo�e mie� na ekranie r�ne (kilka czasem kilkana�cie) menu. Wymiany menu w oknie aplikacji mo�na dokona�, za�adowuj�c nowe menu funkcj� LoadMenu() i ustawiaj�c je jako aktualne funkcj� SetMenu(): ... hMenu2 = LoadMenu (hIstance, "Menu2"); SetMenu (hWnd, hMenu2); DrawMenuBar(...); ... Menu i Menu2 powinny by� zdefiniowane w pliku zasob�w *.RC. Po ka�dej zmianie menu nale�y u�y� funkcji DrawMenuBar(), aby wprowadzone zmiany pojawi�y si� na ekranie. Oto przyk�ad stosownego pliku zasob�w: Menu1 MENU BEGIN POPUP "&File" BEGIN MENUITEM "&New" , IDM_NEW MENUITEM "&Save", IDM_SAVE MENUITEM "E&xit", IDM_EXIT END POPUP "&Options" BEGIN MENUITEM "Menu&1", IDM_M1,CHECKED MENUITEM "Menu&2" , IDM_M2 END END Menu2 MENU BEGIN POPUP "&File" BEGIN MENUITEM "&Open", IDM_OPEN MENUITEM "&New" , IDM_NEW MENUITEM "&Save", IDM_SAVE MENUITEM "Save &As", IDM_SAVEAS MENUITEM "&DOS shell", IDM_DOSSHELL...
mikomil