Eine GEM-Menüleiste, die horizontal Am oberen Bildschirmrand in einer vorgegebenen Schriftgrösse erscheint, ist zugegeben sehr praktisch und mit einigen GFA-BASIC-Befehlen auch leicht zu verwalten. Wie wäre es aber z.B., wenn man nicht nur eine Menüleiste, sondern beliebig viele darstellen könnte? Und wie wäre es dann, wenn man diese Menüleisten auf dem Bildschirm dort plazieren könnte, wo man dies gerade haben will, wenn man diese Menüleisten in vier verschieden Schriftgrössen und einer beliebigen Textfarbe zeichnen könnte, wenn man diese Menüleisten nicht nur horizontal sondern auch vertikal zeichnen könnte, wenn ..., wenn ..., wenn ..., das wäre doch nicht schlecht, oder?
Die hier vorgestellten Routinen ermöglichen es, einem Programm auf einfache Weise eine individuelle Note zu geben, ohne auf das bekannte Prinzip der GEM-Menüleisten verzichten zu müssen. Ein Nachteil dieser Routinen soll gleich zu Anfang genannt werden: Es ist nicht möglich. Accessories aus diesen Routinen heraus aufzurufen. Es ist daher sinnvoll, auch die normale Menüleiste zu verwenden, wenn man nicht auf Accessories verzichten will. Das können die Routinen:
Die Data-Zeilen für eine Menüleiste sollten folgendermaßen aufgebaut sein: Der erste String in den Daten ist der erste Menütitel, danach folgen die einzelnen Menüeinträge, abgeschlossen wird das ganze mit einem Leerstring. Dann folgt der nächste Titel, usw., das Ende einer Menüleiste wird mit “***” angegeben. Daran anschließend können Daten für weitere Menüleisten nach dem selben Schema folgen. Wenn das erste Zeichen eines Menüeintrages ein “+” oder ist, wird der Eintrag direkt unwählbar fett (“+”), oder unwählbar hell (“-”) gemacht. Das oder “+” erscheint nicht im Eintrag. Der Aufbau der Daten ist somit fast identisch mit dem von GFA-BASIC für GEM-Menüs verwendeten Prinzip. Die Menüdaten werden mit folgenden Befehlen eingelesen:
Restore >Menülabel<
Gosub Menues_berechnen(n)
Restore >Menülabel<
Gosub Menues_initialisieren (x_res,y_res)
n ist die Anzahl der Menüleisten, die am Stück eingelesen werden sollen. In x_res und y_res müssen die maximal möglichen Bildschirmkoordinaten angegeben werden (z.B. 639 und 399 für hohe Auflösung). Das ist schon alles, was zur Initialisierung notwendig ist, danach kann es losgehen.
Gosub Menu_paint(m_nr,x1,y1,x2,y2,r1!,r2!,v!,k!) zeichnet und aktiviert eine Menüleiste.
m_nr entspricht der laufenden Nummer der Menüleiste (m_nr ≥0).
x1,y1,x2,y2 sind die Bildschirmkoordinaten der Menüleiste.
x1 und y1 sind die Koordinaten der in Schreibrichtung linken unteren Ecke des Menüs.
x2 und y2 geben dabei jeweils die Breite des Menüs an, wobei die Menüleiste immer mindestens so breit ist, wie es für den Menütext benötigt wird. Wird als Wert -1 angegeben, nimmt die Routine Standardwerte an.
r1! = Richtung 1
r1! = false => horizontal
r1! = true => vertikal
r2! = Richtung 2
r2! = false => Pull-Downs nach unten oder rechts
r2! = true=> Pull-Downs nach oben oder links
v! = Versteckt-Flag
v! = false => Menü normal
v! = true => Menü versteckt
k! = Mausklick-Flag
k! = false => Pull-Downs normal
k! = true => Pull-Downs erscheinen erst nach Mausklick
GosubOn_menu(*m_nr,*m_p) fragt alle aktiven Menüleisten ab und gibt evtl. in m_nr die Nummer der Menüleiste, in m_p die Nummer des angewählten Eintrags zurück. Dieser Befehl sollte möglichst in eine Schleife gesetzt werden (z.B. DO..LOOP). Die Variablen müssen als Pointer eingesetzt werden, um eine Rückgabe zu ermöglichen!
Gosub Menu_image(m_nr,tg,f) setzt Textgröße und Farbe eines Menüs.
tg = Textgröße (0..3)
f = Textfarbe (0..15)
Gosub Menu_text(m_nr,m_p,a,t$) ändert Attribut und Text eines Eintrages.
m_p = Nummer des Menüeintrags
a = Attribut des Eintrags
a = -1 => keine Änderung,
a = 0 => normal,
a = 1 => fett (unwählbar),
a = 2 => hell (unwählbar),
a = 3 => normal mit Häkchen,
a ≥ 4 => hell mit Häkchen
t$ = Menüeintrag-String
wenn t$ = dann keine Änderung
Gosub Menu_kill(m_nr) löscht eine Menüleiste vom Bildschirm, um Änderungen in der Lage des Menüs oder in der Titelzeile zu ermöglichen.
Gosub Menu_lock(m_nr) sperrt die Bearbeitung eines Menüs, um z.B. einen Aufruf der in ihm enthaltenen Einträge vorübergehend zu vermeiden, oder in Verbindung mit Gosub Menu_kill(m_nr) ein Menü komplett zu entfernen. Die Daten des Menüs bleiben dabei erhalten und können für ein erneutes aktivieren der Menüleiste wieder genutzt werden. Alle anderen Prozeduren sollten nach Möglichkeit nicht genutzt werden, da das den normalen Ablauf mit hoher Wahrscheinlichkeit stören würde.
Sämtliche von den Routinen benutzten externen Variablen haben ein M_ vorangestellt. Daher dürfte es, wenn man im übrigen Programm Variablennamen mit einem solchen Anfang vermeidet, nicht zu ungewollten Effekten kommen. Im Allgemeinen sollte man darauf verzichten, auf Variablen, die von den Routinen benutzt werden, direkt zuzugreifen, “legale” Ausnahmen davon sind:
Die Variable M_action! kam dazu genutzt werden, um fest-zustellen, ob eine Menüfunktion aktiviert wurde oder nicht. Falls M_action!=True ist, sollte man nicht im Bildschirm zeichnen, da es dann z.B. möglich wäre, daß ein ausgeklapptes Pull-Down-Menü “im Weg” ist.
' ***********************************************
' * Menü-Library von Matthias Andrä
' * (c) MAXON Computer GmbH
' ***********************************************
'
Procedure Menues_berechnen(N%)
' Dimensionierungen der Arrays vornehmen
' und maximale Ausmaße der Menüs berechnen
'
Local I%,M%,T$,M_mpd%,M_mtit%
'
M_max%=Max(0,N%-1)
Dim M_maxpulldown%(M_max%),M_maxtitel%(M_max%)
Dim M_hidden!(M_max%),M_klick!(M_max%),M_back$(M_max%),M_back!(M_max%)
Dim M_paint!(M_max%),M_aktiv!(M_max%), M_text_size%(M_max%)
Dim M_th%(M_max%),M_tb%(M_max%),M_tof%(M_max%), M_color% (M_max%)
Dim M_x% (M_max%) , M_y% (M_max%) , M_x1% (M_max%) , M_y1%(M_max%)
Dim M_direction1!(M_max%),M_direction2!(M_max%)
'
Clr M_mpd%,M_mtit%
For M%=0 To M_max%
M_maxpulldown%(M%)=0
M_maxtitel%(M%)=0
Clr I%
M_titel!=True
Repeat
Read T$
Exit If T$="***"
If M_titel!
Inc M_maxtitel%(M%)
Clr I%,M_titel!
Endif
If T$=""
M_titel!=True
M_maxpulldown%(M%)=Max(M_maxpulldown%,I%)
Endif
Inc I%
Until T$="***"
Dec M_maxpulldown%(M%)
Dec M_maxtitel%(M%)
M_mpd%=Max(M_mpd%,M_maxpulldown%(M%))
M_mtit%=Max(M_mtit%,M_maxtitel%(M%))
Next M%
'
Dim Menu$(M_max%,M_mtit%,M_mpd%)
Dim Menu_style%(M_max%,M_mtit%,M_mpd%)
Return
Procedure Menues_initialisieren(X_res%,Y_res%)
' Initialisiert die Daten der Menüleisten
'
Local A$
M_xres%=X_res%
M_yres%=Y_res%
For M%=0 To M_max%
For M_titel%=0 To M_maxtitel%(M%)
For M_pulldown%=0 To M_maxpulldown%(M%)
Let Menu$(M%,M_titel%,M_pulldown%)=""
Next M_pulldown%
Next M_titel%
For M_titel%=0 To M_maxtitel%(M%)
For M_pulldown%=0 To M_maxpulldown%(M%)+1
Read T$
Exit If T$=""
If M_pulldown%=0
Let Menu$(M%,M_titel%,M_pulldown%)=" "+T$+" "
Else
A$=Left$(T$)
If A$="-" Or A$="+"
@Menu_nr(M%,M_titel%,M_pulldown%,*M_punkt%)
@Menu_text(M%,M_punkt%,Asc(A$)-43-(Asc(A$)=43),"")
T$=Mid$(T$,2)
Endif
Let Menu$(M%,M_titel%,M_pulldown%)=T$
Endif
Next M_pulldown%
Next M_titel%
Read T$
Next M%
For M%=0 To M_max%
If Xbios(4)=2
Restore L_m2groesse
Else
Restore L_m1groesse
Endif
Read M_text_size%(M%),M_tb%(M%),M_th%(M%),M_tof%(M%)
M_color%(M%)=1
M_hidden!(M%)=False
Next M%
M_tx%=-1
M_ty%=-1
M_pulldown%=-1
M_pd%=-1
Clr M_titel%
Return
Procedure Menu_image(M%,Groesse%,Farbe%)
' Setzen von Textgroesse und Farbe der Menüleiste
'
Local I%
L_m_groesse:
Data 4,6,6,0
L_m1groesse :
Data 6,8,8,0
L_m2groesse:
Data 13,8,16,2
Data 32,16,32,4
'
If M%>=0 And M%<=M_max%
If Groesse%>=0
Restore L_m_groesse
Groesse%=Min(3,Groesse%)
For I%=0 To Groesse%
Read M_text_size%(M%),M_tb%(M%),M_th%(M%),M_tof%(M%)
Next I%
Endif
If Farbe%>=0
M_color%(M%)=Min(15,Farbe%)
Endif
Endif
Return
Procedure Menu_paint(M%,X1%,Y1%,X2%,Y2%,Richtung1!,Richtung2!,Versteckt!,Klick!)
' Übernahme der Koordinaten für Menüleiste
' und Menüleiste zeichnen ( falls nicht versteckt ! )
'
If M%>=0 And M%<=M_max%
M_direction1!(M%)=Richtung1!
M_direction2!(M%)=Richtung2!
M_hidden!(M%)=Versteckt!
M_klick!(M%)=Klick!
M_aktiv!(M%)=True
If M_direction1!(M%)
M_y%(M%)=M_yres%
M_y1%(M%)=0
If Y1%>=0
M_y%(M%)=Min(M_yres%,Max(Y1%,M_tb%(M%)*2))
Endif
If Y2%>=0
M_y1%(M%)=Min(Y1%,Y2%)
Endif
M_x%(M%)=Max(M_th%(M%),Min(M_xres%-2,X1%))
If Not M_hidden!(M%)
@M_paint_ver
Endif
Else
M_x%(M%)=0
M_x1%(M%)=M_xres%
If X1%>=0
M_x%(M%)=Min(X1%,M_xres%-M_tb%(M%)*2)
Endif
If X2%>=0
M_x1%(M%)=Min(Max(X1%,X2%),M_xres%)
Endif
M_y%(M%)=Max(M_th%(M%),Min(M_yres%-2,Y1%))
If Not M_hidden!(M%)
@M_paint_hor
Endif
Endif
Endif
Return
Procedure On_menu(Adresse1%,Adresse2%)
' Fragt Menüleisten ab und gibt die Nummer des Menüs und
' eines evtl, angeklickten Menüpunktes zurück
'
Local Mn%,M%,Mx%,My%,Mk%,M_end!
Mouse Mx%,My%,Mk%
Clr M_end!,M_action!
If Menu_nr%>-1 And (Not M_pulldown! And M_invt!)
@Menu_off(Menu_nr%)
Endif
For M%=0 To M_max%
If M_aktiv!(M%)
If M_pd%=M% Or M_pd%=-1
Mn%=-1
If M_pulldown!
M_action!=True
If Mx%>M_pdx% And Mx%<M_pdx1% And My%>M_pdy% And My%<M_pdy1%-1
M_pnr%=(My%-M_pdy%-1)/M_th%(M%)+1
If Menu_style%(M%,M_titel%,M_pnr%)=0 Or Menu_style%(M%,M_titel%,M_pnr%)=3
If M_nr%<>M_pnr%
If M_punkt!
Put Max(0,M_pdx%+1),Max(0,M_py%),M_punkt$,10
Endif
M_py%=(M_pnr%-1)*M_th%(M%)+M_pdy%+1
M_py1%=M_py%+M_th%(M%)
Get Max(0,M_pdx%+1),Max(0,M_py%),Min(M_xres%,M_pdx1%-1),Min(M_yres%,M_py1%),M_punkt$
Put Max(0,M_pdx%+1),Max(0,M_py%),M_punkt$,10
M_punkt%=M_pnr%
M_nr%=M_pnr%
M_punkt!=True
Endif
If Mk%=1
@Menu_nr(M%,M_titel%,M_punkt%,*Mn%)
@Menu_pull_down_back
M_end!=True
Goto L_on_menu_end
Endif
Else
Goto L_mpunkt_invert
Endif
Else
L_mpunkt_invert:
If M_punkt!
Put Max(0,M_pdx%+1),Max(0,M_py%),M_punkt$,10
Clr M_punkt!,M_nr%,M_pnr%,M_punkt%
Endif
Endif
Endif
If M_direction1!(M%)
If My%>=M_y1%(M%) And My%<=M_y%(M%) And Mx%>=M_x%(M%)-M_th%(M%) And Mx%<=M_x%(M%)+2
M_action!=True
If M_hidden!(M%) And Not M_back!(M%)
@M_paint_ver
Endif
If M_pulldown! Or (Mk%=1 And M_klick!(M%)) Or Not M_klick!(M%)
Y%=M_y%(M%)
For M_t%=0 To M_maxtitel%(M%)
Sub Y%,Len(Menu$(M%,M_t%,0))*M_tb%(M%)
Exit If Y%<My%
Next M_t%
Y%=Max(0,Y%)
If Y%<My%
If Y%<>M_ty%
@Menu_inv(M%)
Get M_x%(M%)-M_th%(M%)-M_direction2!(M%),Y%,M_x%(M%)+1-M_direction2!(M%),Y%+Len(Menu$(M%,M_t%,0))*M_tb%(M%),Inv_titel$
Put M_x%(M%)-M_th%(M%)-M_direction2!(M%),Y%,Inv_titel$,10
M_ty%=Y%
M_titel%=M_t%
M_invt!=True
Endif
Endif
Endif
Else
Goto L_pulldown_delete
Endif
Else
If My%>=M_y%(M%)-M_th%(M%) And My%<=M_y%(M%)+2 And Mx%>=M_x%(M%) And Mx%<=M_x1%(M%)
M_action!=True
If M_hidden!(M%) And Not M_back!(M%)
@M_paint_hor
Endif
If M_pulldown! Or (Mk%=1 And M_klick!(M%)) Or Not M_klick!(M%)
X%=M_x%(M%)
For M_t%=0 To M_maxtitel%(M%)
Add X%,Len(Menu$(M%,M_t%,0))*M_tb%(M%)
Exit If X%>Mx%
Next M_t%
If X%>Mx%
Sub X%,Len(Menu$(M%,M_t%,0))*M_tb%(M%)
If X%<>M_tx%
@Menu_inv(M%)
Get X%,Max(0,M_y%(M%)-M_th%(M%)-M_direction2!(M%)),Min(M_xres%,Min(M_xres%,X%+Len(Menu$(M%,M_t%,0))* M_tb%(M%))),Min(M_yres%,M_y%(M%)+1-M_direction2!(M%)),Inv_titel$
Put X%,Max(0,M_y%(M%)-M_th%(M%)-M_direction2!(M%)), Inv_titel$,10
M_tx%=X%
M_titel%=M_t%
M_invt!=True
Endif
Endif
Endif
Else
L_pulldown_delete:
If M_paint!(M%) And ((M_pulldown! And Mk%=1) Or Not M_pulldown!)
@Menu_pull_down_back
@Menu_off(M%)
Clr M_titel%,M_invt!
M_back!(M%)=False
M_ty%=-1
M_tx%=-1
Endif
Endif
Endif
If M_invt! And M_titel%<>M_pulldown%
@Menu_pull_down
Endif
L_on_menu_end:
*Adresse1%=M%
*Adresse2%=Mn%
Endif
Endif
Exit If M_end!
Next M%
Return
Procedure Menu_text(M%,M_n%,S%,T$)
' Ändert Menüeinträge
'
Local I%,N%,Mn%
If M%>=0 And M%<=M_max%
Clr Mn%
For I%=0 To M_maxtitel%(M%)
For N%=0 To M_maxpulldown%(M%)
Exit If Mn%=M_n%
Sub Mn%,Menu$(M%,I%,N%)<>""
Next N%
Exit If Mn%=M_n%
Next I%
If Mn%=M_n%
If S%>=0
Let Menu_style%(M%,I%,N%)=S%
Endif
If T$<>""
Let Menu$(M%,I%,N%)=T$
Endif
Endif
Endif
Return
Procedure Menu_kill(M%)
' Löscht angegebene Menüleiste
'
If M%>=0 And M%<=M_max%
If M_direction1!(M%)
Put M_x%(M%)-M_th%(M%),M_y1%(M%),M_back$(M%),3
Else
Put M_x%(M%),M_y%(M%)-M_th%(M%),M_back$(M%),3
Endif
Clr M_titel%, M_invt!
M_paint!(M%)=False
M_back!(M%)=False
Endif
Return
Procedure Menu_lock(M%,Lock!)
' Sperrt Menübearbeitung, oder hebt Sperre auf
'
M_aktiv!(M%)=Not Lock!
Return
'
' **** interne Routinen für Menü-Library ****
'
Procedure Menu_inv(M%)
If M_invt!
If M_direction1!(M%)
Put Max(0,M_x%(M%)-M_th%(M%)-M_direction2!(M%)),M_ty%,Inv_titel$,10
M_ty%=-1
Else
Put M_tx%,Max(0,M_y%(M%)-M_th%(M%)-M_direction2!(M%)),Inv_titel$,10
M_tx%=-1
Endif
Clr M_titel%,Inv_titel$,M_invt!
Endif
Return
Procedure Menu_off(M%)
@Menu_inv(M%)
If M_hidden!(M%)
@Menu_kill(M%)
Endif
Return
Procedure M_leiste_vorbereiten
Clr M_leiste$
For M_titel%=0 To M_maxtitel%(M%)
M_leiste$=M_leiste$+Menu$(M%,M_titel%,0)
Next M_titel%
M_paint!(M%)=True
M_back!(M%)=True
Graphmode 1
Color 1
Return
Procedure M_paint_hor
@M_leiste_vorbereiten
M_x1%(M%)=Min(M_xres%,Max(M_x%(M%)+Len(M_leiste$)*M_tb%(M%),M_x1%(M%)))
Get M_x%(M%),M_y%(M%)-M_th%(M%),M_x1%(M%),M_y%(M%)+2,M_back$(M%)
Put M_x%(M%),M_y%(M%)-M_th%(M%),M_back$(M%),0
Deftext M_color%(M%),0,0,M_text_size%(M%)
Text M_x%(M%),M_y%(M%)-M_tof%(M%),M_leiste$
If M_direction2!(M%)
Line M_x%(M%),M_y%(M%)-M_th%(M%),M_x1%(M%),M_y%(M%)-M_th%(M%)
Else
Line M_x%(M%),M_y%(M%)+2,M_x1%(M%),M_y%(M%)+2
Endif
Return
Procedure M_paint_ver
@M_leiste_vorbereiten
M_y1%(M%)=Max(0,Min(M_y%(M%)-Len(M_leiste$)*M_tb%(M%),M_y1%(M%)))
Get M_x%(M%)-M_th%(M%),M_y1%(M%),M_x%(M%)+2,M_y%(M%),M_back$(M%)
Put M_x%(M%)-M_th%(M%),M_y1%(M%),M_back$(M%),0
Deftext M_color%(M%),0,900,M_text_size%(M%)
Text M_x%(M%)-M_tof%(M%),M_y%(M%),M_leiste$
If M_direction2!(M%)
Line M_x%(M%)-M_th%(M%),M_y%(M%),M_x%(M%)-M_th%(M%),M_y1%(M%)
Else
Line M_x%(M%)+2,M_y%(M%),M_x%(M%)+2,M_y1%(M%)
Endif
Return
Procedure Menu_pull_down
Local I%,Mn%
@Menu_pull_down_back
Clr I%,M_pdb%
Repeat
Inc I%
M_pdb%=Max(M_pdb%,Len(Menu$(M%,M_titel%,I%))*M_tb%(M%))
Until I%>=M_maxpulldown%(M%) Or Menu$(M%,M_titel%,I%)=""
Inc M_pdb%
Add I%,Menu$(M%,M_titel%,I%)=""
M_pdl%=I%*M_th%(M%)+2
If M_direction1!(M%)
If M_direction2!(M%)
M_pdx1%=M_x%(M%)-M_th%(M%)
M_pdx%=M_pdx1%-M_pdb%
Else
M_pdx%=M_x%(M%)+2
M_pdx1%=M_pdx%+M_pdb%
Endif
M_pdy1%=M_ty%+Len(Menu$(M%,M_titel%,0))*M_tb%(M%)
M_pdy%=M_pdy1%-M_pdl%
Else
M_pdx%=M_tx%
M_pdx1%=M_tx%+M_pdb%
If M_direction2!(M%)
M_pdy1%=M_y%(M%)-M_th%(M%)
M_pdy%=M_pdy1%-M_pdl%
Else
M_pdy%=M_y%(M%)+2
M_pdy1%=M_pdy%+M_pdl%
Endif
Endif
Y%=M_pdy%-M_tof%(M%)
M_pulldown%=M_titel%
M_pulldown!=True
M_pd%=M%
Graphmode 1
Get Max(0,M_pdx%),Max(0,M_pdy%),Min(M_xres%,M_pdx1%),Min(M_yres%,M_pdy1%),M_pulldown$
Deffill 1,0,0
Pbox M_pdx%,M_pdy%,M_pdx1%,M_pdy1%
For Mn%=1 To I%
Add Y%,M_th%(M%)
If Menu_style%(M%,M_titel%,Mn%)<3
If Menu_style%(M%,M_titel%,Mn%)=2 And M_text_size%(M%)=4
Deftext M_color%(M%),3,0,M_text_size%(M%)
Else
Deftext M_color%(M%),Menu_style%(M%,M_titel%,Mn%),0,M_text_size%(M%)
Endif
Text M_pdx%+1,Y%,Menu$(M%,M_titel%,Mn%)
Else
If Menu_style%(M%,M_titel%,Mn%)=3
Deftext M_color%(M%),0,0,M_text_size%(M%)
Else
If M_text_size%(M%)=4
Deftext M_color%(M%),3,0,M_text_size%(M%)
Else
Deftext M_color%(M%),2,0,M_text_size%(M%)
Endif
Endif
Text M_pdx%+1,Y%,Menu$(M%,M_titel%,Mn%)
Text M_pdx%+2,Y%,""
Endif
Next Mn%
Return
Procedure Menu_pull_down_back
If M_pulldown!
Put Max(0,M_pdx%),Max(0,M_pdy%),M_pulldown$,3
M_pulldown%=-1
M_pd%=-1
Clr M_punkt!,M_pulldown!,M_pnr%,M_nr%
Endif
Return
Procedure Menu_nr(M%,M_t%,M_n%,Adresse%)
Local I%,N%,Nm%
If M%>=0 And M%<=M_max%
Clr Nm%
For I%=0 To M_maxtitel%(M%)
For N%=0 To M_maxpulldown%(M%)
Exit If I%=M_t% And N%=M_n%
Sub Nm%,Menu$(M%,I%,N%)<>""
Next N%
Exit If I%=M_t% And N%=M_n%
Next I%
If I%>M_maxtitel%(M%)
Clr Nm%
Endif
*Adresse%=Nm%
Endif
Return