JOBlF:Н '!ÝGadToolsMenus door: E v/d Oosterkamp (CCCP). Inleiding Sinds de introductie van Kickstart2.0 zijn er vele verbeteringen aan ons besturingssysteem aangebracht. Een voorbeeld hiervan is de GadTools.library. Met deze library kan de programmeur snel, handig en makkelijk complexe gadgets en menus in zijn applicatie toepassen. Het gebruik van gadtools menu's is enorm verbeterd tenopzichte van het 'oude' intuition menu. Het gadtools menu is fontsensetive, de programmeur hoeft daar zelf niets voor te doen. Coderswalhalla! MenuDefinitie Een gadtools menu bestaat uit een array met daarin componenten als Menuentry, menuitem en submenu. Doordat het laatste component van het type MN_END is weet gadtools dat het menu klaar is. Eenvoorbeeldje: 8܌ GTNewMenu: DC.B NM_TITLE,0 ;Eerste menu op balk. "Project". DC.L Project ;APTR Tekst. DC.L 0 ;APTR letter(!). DC.W 0 ;UWORD flags. DC.L 0 ;ULONG mutual exclude. DC.L 0 ;ULONG userdata. DC.B NM_ITEM,0 ;Eerste Item onder "project". "About". DC.L About ;"About" DC.L About ;Eerste letter van "About". "A". DC.W 0 DC.L 0 DC.L OpenAbout ;ULONG userdata. > Komt later. DC.B NM_ITEM,0 ;Tweede Item onder "project" DC.L NM_BARLABEL ;Scheidingsstreep! DC.L 0 DC.W 0 DC.L 0 DC.L 0 ;ULONG userdata. > Komt later. DC.B NM_ITEM,0 ;Derde item onder "project". "Quit". DC.L Quit ;"Quit" DC.L Quit ;"Q" DC.W 0 DC.L 0 DC.L ExitAll ;ULONG userdata. > Komt later. DC.B NM_END,0 ;Einde van gadtoolsmenu array. 8܌ Het array op de vorige bladzijde geeft een menubalk met een entry, "Project" en onder die entry zitten twee(!) menuitems met shortcut en ze zijn gescheiden door een streep (de "barlabel"). De eerstgenoemde items komen altijd boven de latergenoemden en de eerst genoemde menuentrys komen altijd links van de latergenoemden. De plaats in het array bepaald dus de plaats in het uiteindelijke menu. MenuGeneratie Het array zal natuurlijk niet zichzelf aan een window hangen. Dit moet de programmeur gadtools laten doen. Hiervoor zal gadtools namelijk het array omzetten in de aloude bekende intuitionmenustructuren: MOVE.L GadBase(PC),a6 ;a6 := GadToolsBase. LEA.L GTNewMenu(PC),a0 ;APTR GadTools MenuArray. LEA.L MenuTags(PC),a1 ;APTR Taglist. (meestal leeg). JSR CREATEMENUS(a6) ;Maak de structuren aan. MOVE.L d0,MenBase ;Sla menustrip op. In "MenBase" wordt nu het adres gegeven waarop de lijst met intuitionmenu's begint. Voordat deze lijst ook werkelijk gebruikt kan worden moeten de plaatsen van de entry's, items en subitems nog worden berekend. Dit gebeurt fontafhankelijk. Wanneer de gebruiker dus het systeemfont veranderd (20 punten in plaats van acht) blijft het menu nog steeds leesbaar. 8܌ Uiteraard moet er naar een foutafhandelingsroutine worden gesprongen wanneer de functie "CREATEMENUS" een nul afgeeft ipv een menustrip. MOVE.L GadBase(PC),a6 ;a6 := GadToolsBase. MOVE.L MenBase(PC),a0 ;APTR Menustrip. MOVE.L VisualInfo(PC),a1 ;APTR Visualinfo structuur. LEA.L MenuTags(PC),a2 ;APTR Taglist. (meestal leeg). JSR LAYOUTMENUS(a6) ;Style het menu. De "VisualInfo" (APTR in register a1) bevat alle informatie over het gebruikte font, resoluties en schermafmetingen. Uiteraard dient deze eerst met de functie "GETVISUALINFO" te worden verkregen. Na "LAYOUTMENUS" kan het menu via de standaard intuition routines worden gebruikt. Dit heeft een restrictie: In plaats van de Execroutines "GETMSG" en "REPLYMSG" moeten nu wel de gadtools equivalenten "GT_GETMSG" en "GT_REPLYMSG" worden gebruikt! MenuGebruik GadTools menu's leveren net als hun intuition equivalenten IDCMPmessages op van de msgclass "IDCMP_MENUPICK". In het code veld van de IntuiMSG staat het "MenuNumber". Dit is een samengesteld WORD dat aangeeft het hoeveelste subtem van het hoeveelste item van het hoeveelste entry deze message heeft veroorzaakt. Dit getal is uniek voor elk onderdeeltje in het menu. 8܌ Je kunt tabellen aanmaken met sprongadressen, je kunt een eindeloze rij vergelijkingsopdrachten met conditionele sprongen gebruiken, en allemaal om naar de juiste routine te springen nadat de genbruiker iets van je applicatie vroeg. Maar dit kan handiger... In de menuarray zat het ULONG "userdata". Deze data wordt iedere keer door gadtools aan het einde van de door "CREATEMENUS" aangemaakte intuition structuur geplakt. Door in deze ULONG het sprongadres te zetten van de functie die je wilt aanroepen heb je altijd de gewenste routine bij de hand. Zodra je het MenuNumber uit de IntuiMSG hebt gehaald kun je met de intuition functie "ITEMADDRESS" het adres van het item ophalen en je weet dat aan het einde daarvan (offset 34) je adres staat: MenuPick: MOVE.L IntBase(PC),a6 ;a6 = IntBase. MOVE.L MenBase(PC),a0 ;APTR MenuStrip. MOVE.W MenuNumber(PC),d0 ;UWORD Menunummer. JSR ITEMADDRESS(a6) ;Haal adres op. MOVE.L d0,a0 ;Adres verpotten. MOVE.L 34(a0),a0 ;ULONG Userdata ophalen. JMP (a0) ;Bespring juiste routine. Het kan geen kwaad het een en ander te testen voordat je gaat springen! Wanneer je nu in het array items toevoegd en dergelijke heeft dit totaal geen invloed op andere items ondanks dat alle MenuNumbers dan veranderen. Dit principe kun je ook bij intuition menu's gebruiken: Je moet dan gewoon zelf op offset 34 die extra APTR toevoegen. 8܌ Bij afsluiten van je applicatie moet uiteraard het door gadtools gereserveerde geheugen voor je menu worden vrijgegeven: MOVE.L GadBase(PC),a6 ;a6 = GadToolsBase. MOVE.L MenBase(PC),a0 ;APTR menustrip. JSR FREEMENUS(a6) ;Geef Menu's vrij. Hierna kan de VisualInfo worden vrijgegeven met FREEVISUALINFO. Let er wel op dat voordat je FREEMENUS aanroept het menu vrij hebt gemaakt van alle windows! Hiervoor gebruik je de intuition functie "CLEARMENU" dat de tegenhanger is van de functie "SETMENU" waarmee je het menu aan een window had verbonden. Wanneer je meerdere windows hebt die bij een applicatie horen, dan kan het handig zijn om ze allemaal van dezelfde menustrip gebruik te laten maken (en van dezelfde "MenuPick" routine...). NaWoord Met de Gadtool.library heeft Commodore iets moois gewrocht. Experimenteer er wat mee en raak er volledig van onder de indruk. Succes! Edwin.