Smalltalk hat sie, der Amiga hat sie, aber GEM hat sie merkwürdigerweise nicht. Popup-Menüs sind in Aussehen und Wirkung Dropdown-Sorten ganz ähnlich, können aber nach Wunsch an jedem Platz des Bildschirms und Programmes!) eingesetzt werden.
Da sie leicht zu handhaben sind, haben sie außerdem den Vorteil, daß der Benutzer die gebotenen Alternativen da zu sehen bekommt, wohin er das Auge gerichtet hat: zum Beispiel gerade da, wo der Mauszeiger sich befand, als die Maustaste betätigt wurde. Dies macht die Benutzerführung Ihres Programmes angenehmer, direkter und schneller.
Die Syntax ist möglichst einfach:
Popup(X,Y,Popup$,Reply)
X und Y sind die Koordinaten des oberen, linken Punktes des Menüs. Sie werden automatisch angepaßt, sollte durch die Wahl von X und Y das Menü (teilweise) außerhalb des Bildschirms fallen.
Durch Popup$ wird bestimmt, wie das Menü aussieht.
Es ist von folgendem Aufbau:
[-]EintragO|[-]Eintrag1|....
Das “|” Zeichen dient zur Trennung der einzelnen Einträge. Das optionale Minuszeichen [-] bedeutet, daß der darauffolgenden Eintrag dünn (disabled) darzustellen sei. Das erste Minuszeichen wird nicht ausgegeben. Beispiel :
" Hilfe |-------| Ändern | Löschen "
Es gibt hier vier Menüpunkte, wobei der zweite Eintrag dünn dargestellt wird mit 15(!) Minuszeichen.
Geben Sie nun
"- Hilfe |-------| Ändern | Löschen "
als Popup$ ein, dann wird auch “Hilfe” dünn ausgegeben (ohne Minuszeichen).
Das Ergebnis wird in Reply zurückgegeben. Im obenstehenden Beispiel ist das also 0, wenn “Hilfe”, 2, wenn “Ändern” und 3, wenn “Löschen” vom Benutzer gewählt wurde usw. Das Ergebnis ist -1, wenn außerhalb des Menüs geklickt oder wenn ein “disabled”-Menüpunkt gewählt wurde.
Hoffentlich spricht das Listing des Programmes für sich. Es gibt jedoch ein paar Punkte, die ich verdeutlichen muß.
Hans Heemskerk
' ****************************************************
' Popupmenues in OMIKRON.Basic (c) Hans Heemskerk 1988
'
' Syntax
' Popup(X,Y,Popup$,Reply)
' X,Y : Geben die Koordinaten des oberen, linken Punktes an.
' Popup$="(-)Eintrag0|(-)Eintrag1|....."
' (-) gibt an. ob der Eintrag "disabled" (duenn)
' darzustellen ist.
' Das erste Minuszeichen wird dabei nicht gezeichnet!
' Reply : Das Ergebnis = 0,1,2. .. fuer "able"-
' Menuepunkte. oder
' = -1 nenn ausserhalb des Menues
' geklickt oder ein "disabled"-Menuepunkt
' gewaehlt wurde.
'
' Fuer jede Bildschirmaufloesung geeignet.
'
'
' ************************************************
' HAUPTPROGRAMM
' ************************************************
PRINT CHR$(27);"f";: ' Cursor Aus ..
FILL COLOR =1: FILL STYLE =2,4: ' Desktopartiger Hintergrund ..
PBOX 0,0,640,400
MOUSEON
REPEAT
Popup( MOUSEX , MOUSEY ," Diese Popupmenues | erscheinen gerade |
da, wo der | Mauszeiger | sich befindet |-------------------------|
Quit ",R)
UNTIL R=6
MOUSEOFF
END
' ************************************************
'
' Procedure Popup : Die eigentliche Prozedur.
'
' Benutzte Variablen
' Anzahl : Anzahl der Menuepunkte
' I1,I2,Pop$ : Hilfsvariablen
' Breite.Hoehe : Dimensionen des Menues
' Buffer$ : Der Bildschirmausschnitt wird in diesen Puffer gerettet.
' Ch,Cw : Charakter-Hoehe und -Breite (sind Resolutionsabhaengig).
' Sh,Sw : Screen Hoehe und Breite (ebenfalls).
'
' ACHTUNG! Wenn Sie Windows u/o Dropdownmenus benutzen,
' müssen Sie die REMs vor den Wind_Update Anrufe entfernen.
'
' ************************************************
DEF PROC Popup(X,Y,Popup$,R Reply)
LOCAL Anzahl,I1,I2,Breite,Hoehe,Buffer$,Pop$
LOCAL Ch=8-8*( PEEK($44C)=2),Cw=8' Character-Breite und -Hoehe ..
LOCAL Sh=200-200*( PEEK($44C=2),Sw=640*( PEEK($44C)=0)*320' Bildschirmgroesse.
' Wind_Update(3) * Falls Sie Dropdown-Menues u/o Windows benutzen.
Zeichne_Popup_Menu
REPEAT UNTIL MOUSEBUT =0: ' Damit es nicht wieder sofort verschwindet ..
' Mausueberwachung ..
REPEAT
Finde_Eintrag(I2)
IF I2<Anzahl AND MID$(Pop$,I2+1,1)=CHR$(1) THEN
Invertiere(X+1,Y+(Ch+2)#I2+1,Breite-2,(Ch+2))
REPEAT Finde_Eintrag(I1) UNTIL I1<>I2 OR MOUSEBUT
Invertiere(X+1,Y+(Ch+2)*I2+1,Breite-2,(Ch+2))
ENDIF
UNTIL MOUSEBUT
' Rueckgabe bestimmen ..
Reply=I2
IF I2<Anzahl AND MID$(Pop$,I2+1,1)= CHR$(1) THEN
Touch(X+1,Y+(Ch+2)*I2+1,Breite-2,(Ch+2))
ELSE ' Disabled ..
Reply=-1
ENDIF
' Bildschirm wiederherstellen ..
Putb(X-1,Y-1,Buffer$)
' Wind_Update(2) ' Falls Sie Dropdown Menues u/o Windows benutzen.
RETURN
' ************************************************
'
' Zeichne_Popup_Menu : Diese Prozedur analysiert Popup$.
' bestimmt die Anzahl
' der Menuepunkte, berechnet Hoehe und
' Breite des Menues und zeichnet es.
'
' ************************************************
DEF PROC Zeichne_Popup_Menu
' Popup$ analysieren, Anzahl, Hoehe und Breite berechnen.
I2=1:Anzahl=0:Breite=0
REPEAT
IF MID$(Popup$,I2,1)="-" THEN
Pop$=Pop$+ CHRS(0)
ELSE
Pop$=Pop$* CHRS(1)
ENDIF
Anzahl=Anzahl+1:I1= INSTR(I2,Popup$,"|")
IF I1=0 THEN I1= LEN(Popup$)
Breite= MAX(Breite,I1-I2+( MID$(Popup$,I2+1,1)="-"))
I2=I1+1
UNTIL I1=LEN(Popup$)
' Breite und Hoehe in Pixel ..
Breite=(Breite)*Cw+2:Hoehe=Anzahl*(Ch+2)+2
' Damit das Menu auf dem Bildschirm passt ..
X=X+((X+Breite)>=(Sw-3))*(X+Breite-(Sw-1))-(X<=1)
Y=Y+((Y+Hoehe)>=(Sh-3))*(Y+Hoehe-(Sh-1))-(Y<=1)
IF X<=0 THEN X=1
IF Y<=0 THEN Y=1
FILL STYLE =0,1 ' Weiss ..
MOUSEOFF
' Bildschirminhalt retten ..
Getb(X-1,Y-1,Breite+2,Hoehe+2,Buffer$)
' Dicke box zeichnen ..
PBOX X,Y,Breite,Hoehe: BOX X-1,Y-1,Breite+2,Hoehe+2
' Texte schreiben ..
I2=1
FOR I=0 TO Anzahl-1
I1= INSTR(I2, Popup$, "|")
IF I1=0 THEN I1= LEN(Popup$)+1
IF MID$(Pop$,I+1,1)= CHRS(0) THEN ' Disabled
TEXT STYLE =2
TEXT X+1,Y*Ch+I*(Ch+2), MID$(Popup$,I2+1,I1-I2-1)
ELSE ' Normal
TEXT X+1,Y+Ch+I*(Ch+2), MID$(Popup$,I2,I1-I2)
ENDIF
TEXT STYLE =0 ' Normal
I2=I1+1
NEXT
MOUSEON
RETURN
' ************************************************
'
' Finde_Eintrag : Ermittelt, ueber welchem Menuepunkt der
' Mauszeiger gerade schwebt.
'
' ************************************************
DEF PROC Finde_Eintrag(R I)
FOR I=0 TO Anzahl-1
IF FN Maus_Ist_In(X,Y+I*(Ch+2),Breite,(Ch+2)) THEN EXIT
NEXT
RETURN
' ************************************************
' Invertiere(X,Y.W.H) : Invertiert Rechteck (X,Y,W,H)
' (d.h. Schwarz wird Weiss und umgekehrt).
' ************************************************
DEF PROC Invertiere(X,Y,W,H)
MOUSEOFF : BITBLT X,Y,W,H TO X,Y,W,H,12: MOUSEON
RETURN
' ************************************************
'
' Maus_Ist_In(X,Y,W,H) : Ermittelt, ob der Mauszeiger
' sich in Rechteck (X,Y,W,H) befindet.
' ************************************************
DEF FN Maus_Ist_In(X,Y,W,H)= MOUSEX >X AND MOUSEY >Y AND MOUSEX <X+W ANO MOUSEY <Y+H
' ************************************************
'
' Touch(X,Y,W,H) : Flackereffekt an Rechteck (X,Y,W,H)
'
' ************************************************
DEF PROC Touch(X,Y,W,H)
LOCAL Q: FOR Q=1 TO 8: Invertiere(X,Y,W,H): WAIT .04: NEXT
RETURN
' ************************************************
'
' Getb(X,Y,W,H,R B$) : Rettet auf GFA-aehnliche Weise
' Rechteck (X,Y,W,H) in den Puffer B$.
'
' ************************************************
DEF PROC Getb(X,Y,W,H,R BS)
LOCAL Bytes=(W+15) SHR 4*H*(2 SHL(2- PEEK($44C)))+6
B$= SPACE$(Bytes): MOUSEOFF
BITBLT X,Y,W,H TO LPEEK( VARPTR(B$))+ LPEEK( SEGPTR+28): MOUSEON
RETURN
' ************************************************
'
' Putb(X,Y,B$) : Wiederherstellung des in B$ geretteten
' Rechtecks an (X,Y). (wie in GFA).
' ODER
'
' Putb(X,Y,B$,Modus) : Wiederherstellung des in B$ geretteten Rechtecks
' an (X,Y) mit Verknuepfung Modus
'
' ************************************************
IF 0 THEN DEF PROC Putb(X,Y,B$): LOCAL Modus=3 ELSE DEF PROC Putb(X,Y,B$,Modus)
LOCAL Adr= LPEEK( VARPTR(B$))+ LPEEK( SEGPTR +28)
LOCAL W= WPEEK(Adr+2),H= WPEEK(Adr+4)
MOUSEOFF : BITBLT Adr TO X,Y,W,H,Modus: MOUSEON
RETURN