Blitz-Basic2 - Kurs 6/6

von
Thomas Krippner

[Anmerkung: Thomas hat uns den Kurs zur Verfügung gestellt, ich habe inhaltlich kaum etwas geändert. Ansonsten stehen meine Kommentare in eckigen Klammern, wobei ich nur Vermutungen anstellen kann, was Blitz- Basic angeht. Carsten Jahn]

Übersicht über die Kursteile:

  1. Einführung
  2. Screens
  3. Window-Programmierung
  4. Windows, Gadgets, Peeks
  5. Gadget-Programmierung
  6. Menü-Programmierung

Teil 6: Menü-Programmierung

Hallo, es freut mich, daß Sie bis jetzt durchgehalten haben. Heute geht es um die Menü-Programmierung. Nachdem wir die Gadgets kennengelernt haben, ist das kein Problem mehr. Denn die Auswertung funktioniert analog zu den Beispielen in Teil 5. Also werde ich heute auf die Eigenheiten und die Möglichkeiten unter BB2 eingehen.

Doch nun gehts los:

Unter BB2 gibt es gute Möglichkeiten um ein Menü in einem Window zu erstellen. Wir brauchen deshalb nicht wie bei den Gadgets mit Peeks zu arbeiten, um brauchbare Werte zu erhalten. Mit den Menü-Befehlen von BB2 können wir alle Menüarten des OS abdecken und sie leicht erzeugen.

Beginnen wir mit einem Menüpunkt und zwei Untermenüpunkten.

- Window mit Menü:

  WBStartup
  WBenchToFront_
  WbToScreen 0
  Use Screen 0
  *Scr=ActiveScreen
  FH=Peek.w(Peek.l(*Scr+40)+4)
  FN$=Peek$(Peek.l(*Scr+40)+8)

  LoadFont 0,FN$,FH
  Use IntuiFont 0
  Window 0,0,0,300,200,$1008,"Menue Window",1,2
  *Wi0=ActiveWindow
  MenuTitle 0,0,"Erster Titel"

  MenuItem 0,0,0,0,"First Item ","1"
  MenuItem 0,0,0,1,"Second Item ","2"
  SetMenu 0
  Repeat
         FlushEvents
         ev.l=WaitEvent
         If ev=$100 AND *Wi0 = ActiveWindow
                WLocate 1,1
                Select ItemHit
                 Case 0
                  Print "First Item"
                 Case 1
                  Print "Second Item"
                End Select

         End If
  Until ev=$200 AND *Wi0=ActiveWindow
  End
[Die Beispiele sind wieder als Dateien verfügbar: bin.lha.]

Dieses Beispiel ist nicht schwer zu verstehen: Wir benutzen den Workbench-Screen und laden den aktuellen Intuifont ein. Das ist wichtig: bevor ein Menüfeld eingegeben wird, sollte BB2 den aktuellen Intuifont kennen, denn BB2 benutzt den Intuifont für die Menügestaltung. Sollte nun der Screen-Intuifont vom BB2-internen Font abweichen, so kommt es zu Fehldarstellungen und unleserlichen Menüs. Nach dem Öffnen des Windows erstellen wir einen Menütitel. Diesem können wir nur die Menülistennummer, Titelnummer und den Namen mitgeben. Danach werden 2 Items diesem Titel zugewiesen. Hier können wir schon mehrere Parameter angeben, wie Menülistennummer und Flags, aber auch den Namen der Items.

Mit SetMenu 0 weisen wir dem aktuellen Window die Menüliste mit der Nummer 0 zu. In der Repeat-Schleife wird mit $100 festgestellt, ob eine Menüoperation im Fenster erfolgt ist, wenn ja, verzweigen wir mit ItemHit zu den einzelnen Möglichkeiten.

Durch die Angabe nach dem Item-Titel (1,2) werden Tastaturkürzel gesetzt. Diese Menüs sind jetzt auch mit Amiga-Rechts und 1 als auch Amiga-Rechts und 2 zu erreichen. Wenn Sie Tastaturkürzel verwenden, achten Sie darauf, daß der Abstand vom Titelende zum Tastaturkürzel ausreicht, um einen GFX-Teil aufzunehmen, wie es Intuition oder das Zusatzmodul MagicMenu verwenden.

- Window mit Zwei Menü-Titeln


  WbToScreen 0:Use Screen 0
  *Scr=ActiveScreen
  FH=Peek.w(Peek.l(*Scr+40)+4)
  FN$=Peek$(Peek.l(*Scr+40)+8)

  LoadFont 0,FN$,FH
  Use IntuiFont 0
  Window 0,0,0,300,200,$1008,"Menue Window",1,2
  *Wi0=ActiveWindow

  ; erster Titel
  MenuTitle 0,0,"Erster Titel"
  MenuItem 0,0,0,0,"First Item ","1"
  MenuItem 0,0,0,1,"Second Item ","2"

  ; Zweiter Titel
  MenuTitle 0,1,"Zweiter Titel"
  MenuItem 0,0,1,0,"A Item ","A"
  MenuItem 0,0,1,1,"B Item ","B"



  SetMenu 0
  Repeat
         FlushEvents
         ev.l=WaitEvent
         If ev=$100 AND *Wi0 = ActiveWindow
                WLocate 1,1
                Select MenuHit
                 Case 0
                  Select ItemHit
                        Case 0
                         Print "First Item"
                        Case 1
                         Print "Second Item"
                  End Select
                 Case 1
                  Select ItemHit
                        Case 0
                         Print "A Item "
                        Case 1
                         Print "B Item "
                  End Select
                End Select
         End If
  Until ev=$200 AND *Wi0=ActiveWindow
  End

Viel ist nicht hinzugekommen. Wir haben einen zweiten Titel angehängt mit der Titelnummer 1, somit haben auch seine Items diese Titelnummer. Nun stehen wir vor dem Problem, daß ItemHit also immer 0 oder 1 als Wert zurückgibt und wir nicht wissen, ob der erste oder der zweite Titel ausgewählt wurde.

Also brauchen wir eine zweite Schleife die erkennt, ob der Benutzer Titel Eins oder Titel Zwei mit dem entsprechendem Item angewählt hat. Diese Verzweigung ist die MenuHit-Schleife, die 0 für Erster Titel und 1 für Zweiter Titel zurückgibt. Der Rest ist die Wiederholung des ersten Beispiels.

- Window mit Sub-Menü

  WbToScreen 0:Use Screen 0
  *Scr=ActiveScreen
  FH=Peek.w(Peek.l(*Scr+40)+4)
  FN$=Peek$(Peek.l(*Scr+40)+8)

  LoadFont 0,FN$,FH
  Use IntuiFont 0
  Window 0,0,0,300,200,$1008,"Menue Window",1,2
  *Wi0=ActiveWindow

  ; erster Titel
  MenuTitle 0,0,"Erster Titel"
  MenuItem 0,0,0,0,"First Item "
  SubItem 0,0,0,0,0,"Untermenü U ","U"
  SubItem 0,0,0,0,1,"Untermenü W ","W"
  MenuItem 0,0,0,1,"Secont Item ","2"



  ; Zweiter Titel
  MenuTitle 0,1,"Zweiter Titel"
  MenuItem 0,0,1,0,"A Item ","A"
  MenuItem 0,0,1,1,"B Item ","B"



  SetMenu 0
  Repeat
         FlushEvents
         ev.l=WaitEvent
         If ev=$100 AND *Wi0 = ActiveWindow
          WLocate 1,1
          Select MenuHit
                 Case 0
                  Select ItemHit
                        Case 0
                         Select SubHit
                          Case 0
                                Print "Untermenü U"
                          Case 1
                                Print "Untermenü W"
                         End Select
                        Case 1
                         Print "Second Item"
                  End Select
                 Case 1
                  Select ItemHit
                        Case 0
                         Print "A Item "
                        Case 1
                         Print "B Item "
                  End Select
          End Select
         End If
  Until ev=$200 AND *Wi0=ActiveWindow
  End

Auch hier gibt es nur wenig Neues. Nach dem ersten MenuItem geben wir 2 SubItem ein, die wir diesem MenuItem zuweisen. In der Schleife müssen wir jetzt bei Aufruf dieses Items nochmal in eine Schleife verzweigen, die mit SubHit den ausgewählten Eintrag der SubMenüs darstellt. Die Struktur der Menü-Funktionen mit der dazugehörigen Schleife dürfte wohl jetzt verstanden sein. Sie unterscheidet sich nicht groß von der Gadget-Abfrage.

- Menü Flags


  WbToScreen 0:Use Screen 0
  *Scr=ActiveScreen
  FH=Peek.w(Peek.l(*Scr+40)+4)
  FN$=Peek$(Peek.l(*Scr+40)+8)

  LoadFont 0,FN$,FH
  Use IntuiFont 0
  Window 0,0,0,300,200,$1008,"Menue Window",1,2
  *Wi0=ActiveWindow

  ; erster Titel
  MenuTitle 0,0,"Erster Titel"
  MenuItem 0,0,0,0,"First Item "
  SubItem 0,1,0,0,0," Untermenü U"
  MenuItem 0,3,0,1," Second Item"



  ; Zweiter Titel
  MenuTitle 0,1,"Zweiter Titel"
  MenuItem 0,4,1,0," A Item ","A"
  MenuItem 0,2,1,1," B Item ","B"



  SetMenu 0
  Repeat
         FlushEvents
         ev.l=WaitEvent
         If ev=$100 AND *Wi0 = ActiveWindow
          If MenuHit = 0 AND ItemHit = 0
                If MenuChecked(0,MenuHit,ItemHit,SubHit) = True
                 NPrint "AN "
                Else
                 NPrint "AUS"
                End If
          Else
                If MenuChecked(0,MenuHit,ItemHit) = True
                 NPrint "AN "
                Else
                 NPrint "AUS"
                End If
          End If
         End If
  Until ev=$200 AND *Wi0=ActiveWindow
  End

Bis jetzt haben wir nur normale Menüs verwendet, bei der gleich eine Reaktion vom Programm gefordert war. Es gibt aber auch Menüs, bzw. ganze Menüfelder, die man auf einen gewissen Status setzten kann. Diese "Toggens" werden mit BB2 in den Flags gesetzt.

Die Flags sind:

0 = Normales Menü

1 = Ein- und Ausmenü
    (Steht auf Aus)
2 = Eine Liste von Menüs, in der jeweils nur ein Item auf Ein stehen kann
    (Steht auf Aus)
3 = Ein- und Ausmenü
    (Steht auf Ein)
4 = Eine Liste von Menüs, in der jeweils nur ein Item auf Ein stehen kann
    (Steht auf Ein)

Es ist nicht notwendig diese Ein- und Auszustände sofort zu erfassen. Intuition setzt diese nach dem Benutzen automatisch und wir können die Menüs abfragen, wenn wir sie benötigen. Das Abfragen geschieht in BB2 mit MenuChecked, wie es in dem Beispiel steht. Es ist empfehlenswert, diese Menüs wegen der Übersicht des Programms mit True und False und nicht mit -1 und 0 abzufragen. Da wir If-Then-Schleifen kennen und uns die Menü- Funktionen vertraut sind, gibt es sonst nichts zu dem Beispiel zu sagen.

- Window mit 2 Menülisten

  WBStartup
  WBenchtoFront_
  WbToScreen 0:Use Screen 0
  *Scr=ActiveScreen
  FH=Peek.w(Peek.l(*Scr+40)+4)
  FN$=Peek$(Peek.l(*Scr+40)+8)

  LoadFont 0,FN$,FH
  Use IntuiFont 0
  Window 0,0,0,300,200,$1008,"Menue Window",1,2
  *Wi0=ActiveWindow

  ;Menueliste 0
  MenuTitle 0,0,"Erster Titel"
  MenuItem 0,0,0,0,"First Item "
  SubItem 0,1,0,0,0," Untermenü U"
  MenuItem 0,3,0,1," Second Item"
  MenuTitle 0,1,"Zweiter Titel"
  MenuItem 0,4,1,0," A Item ","A"
  MenuItem 0,2,1,1," B Item ","B"
  MenuTitle 0,2,"Zweites Menü"
  MenuItem 0,0,2,0,"Wechseln"

  ; Menueliste 1
  MenuTitle 1,0,"Project"
  MenuItem 1,0,0,0,"First Project "
  SubItem 1,1,0,0,0," Untermenü Pro"
  MenuItem 1,3,0,1," Second Project"



  MenuTitle 1,1,"Aktuell"
  MenuItem 1,4,1,0," A Aktuell ","A"
  MenuItem 1,2,1,1," B Aktuell ","B"

  MenuTitle 1,2,"Zweites Menü"
  MenuItem 1,0,2,0,"Wechseln"

  SetMenu 0:Men=1
  Repeat
         FlushEvents
         ev.l=WaitEvent
         If ev=$100 AND *Wi0 = ActiveWindow
          If MenuHit = 0 AND ItemHit = 0
                If MenuChecked(0,MenuHit,ItemHit,SubHit) = True
                 NPrint "AN "
                Else
                 NPrint "AUS"
                End If
          Else
                If MenuHit = 2
                 If ItemHit = 0 Then SetMenu Men:Men-1:Men*-1
                Else
                 If MenuChecked(0,MenuHit,ItemHit) = True
                  NPrint "AN "
                 Else
                  NPrint "AUS"
                 End If
                End If
          End If
         End If
  Until ev=$200 AND *Wi0=ActiveWindow
  End

In diesem Beispiel soll nun gezeigt werden, wie ein Window zwischen verschiedenen Menülisten wechseln kann. Es ist nicht möglich beide Menülisten gleichzeitig zu benutzen, aber ein Window ist nicht fest an eine Menüliste gebunden. Der praktische Sinn dahinter ist, daß für alle Menüs die ein Window öffnen, eine Menüliste bestehen kann, aber man nur ein Window benötigt, um ihm die gültige Menüliste zuzuweisen.

Zu verstehen gibt es auch hier in diesem Beispiel nicht viel. Das Programm ist nur um den Titel 2 erweitert worden und wechselt bei dessen Aufruf mit Hilfe des SetMenu die Menüliste. Bei dem Beispiel ist eigentlich alles klar, es sind keine Neuerungen hinzugekommen. Die Behandlung der Variable Men ist allerdings noch interessant.

Ein mathematischer Ausflug:

Um jetzt immer die richtige Menüliste, also 0 oder 1, zu bekommen, habe ich die Variable Men eingeführt. Ich möchte nun kurz erklären, wie man auf einfache Weise dessen Zustand ändert, ohne eine IF-Then-Schleife zu benutzen.

Wir setzen die Variablen Men auf den Wert 1:

Men - 1 = 0
Men * -1 = 0

Wir setzen die Variable Men auf 0:

Men - 1 = -1
Men *-1 = 1

Egal mit welchem Zustand Men bei der Formel Men=(Men-1)*-1 ankommt, der Zustand wird danach entweder 0 oder 1 sein, und er wird wechseln - und das ist das, was wir wollen.

Diese Vorgehensweise ist bei Animationen, wo man zwischen Bitmaps, oder bei Spielen, wo man zwischen Slices hin- und herschalten muß, sehr angenehm.

So, Teil 6, sowie der Kurs ist nun beendet und wir haben (hoffentlich) allerhand über Intuition gelernt!

[Mit dem Ende des Kurses von Thomas möchte ich mich von allen Lesern des AmZeigers verabschieden! Carsten Jahn, C.Jahn@gmx.net]


Prev Inhaltsverzeichnis Next
© `99 Der AmZeiger