Benutzeroberflächen - Programme mit Gesicht

 

Auch wenn man oft mit einfachen Textaus- und Eingaben in Programmen auskommen könnte, wird heute von modernen Programmen erwartet, dass die Kommunikation mit dem Anwender eines Programms durch eine 'hübsche' Oberfläche geschieht. Der Anwender möchte nicht einfach eine Textnachricht in der Form 'Soll gedruckt werden (J/N) ?' erhalten, sondern er erwartet ein kleines Fenster mit Titel, z.B. 'Ergebnisdruck', einen entsprechenden Hinweistext, z.B. 'Es sollen die Ergebnisse gedruckt werden. Möchten Sie fortfahren ?', und nicht zuletzt die dazu gehörigen Auswahlflächen wie z.B. 'Ok' und 'Abbruch'.

 

Im BeetleBasic sind solche Elemente zwar nicht direkt vorhanden, aber der Sprachumfang dieses Computersystems ermöglicht es dennoch eine recht leistungsfähige Oberfläche zu erstellen. Vorraussetzung hierfür ist aber leider die Verwendung von TKTerm oder VGATerm als Terminal, da hier die Sonderfunktionen dieser Terminals Verwendung finden.

 

 

Grundlegendes

 

Bevor wir uns überhaupt Gedanken über Fensteraufbau, Schaltflächendefination und Ähnlichem machen können, müssen wir uns erst einmal damit befassen, wie so eine Oberfläche grundlegend funktioniert.

 

Um die Oberfläche zu bedienen, werden in der Praxis meist die Tastatur und eine Maus verwendet. Nun besitzt der BasicBeetle von Haus aus keine Maus, also müssen wir uns mit einem Trick bedienen. Die Maus simulieren wir hier mit den Cursortasten und der [Enter]-Taste. Der Mauscursor wird mit dem Terminal-Textcursor emuliert.

 

Um die Maussteuerung schon einmal zu testen, können wir dieses folgende kleine Programm einmal laufen lassen:

 

  10 REM ********************
20 REM **   BeetleGUI    **
30 REM **    (C) 2012    **
40 REM ** Thomas Krueger **
50 REM ********************
60 REM
70 GOSUB 60000:' Initialisierung der GUI
100 DO:LOOP
60000 REM *****************************
60010 REM ** Initialisierung der GUI **
60020 REM *****************************
60030 REM
60040 DIM JX,JY,K$*1
60080 CLS:PRINT CHR$(20);:JX=40:JY=12: GOSUB 65505
60090 EVERY 10,3 GOSUB 60100:RETURN
60100 REM *** Tastaturabfrage und Auswertung ***
60110 K$=INKEY$:IF K$="" THEN RETURN
60120 SELECT ASC(K$)
60130 CASE 224:IF JY>1 THEN DEC JY:GOSUB 65505:RETURN
60140 CASE 225:IF JX<80 THEN INC JX:GOSUB 65505:RETURN
60150 CASE 226:IF JY<25 THEN INC JY:GOSUB 65505:RETURN
60160 CASE 227:IF JX>1 THEN DEC JX:GOSUB 65505:RETURN
60170 CASE 13:PRINT "*";: GOSUB 65505:RETURN
60490 RETURN
65500 REM *******************
65501 REM ** Cursor setzen **
65502 REM *******************
65503 REM
65505 PRINT CHR$(27);"[";STR$(JY-1);";";STR$(JX-1);"H";:RETURN

 

Nun müssen wir das Demo-Programm noch etwas umschreiben, um es später in unserer Oberfläche zu verwenden. Aber dazu später mehr.

 

Bei diesem Demo kann man mit den Cursortasten die 'Maus' auf dem Bildschirm bewegen. Bei Druck auf [Enter] wird ein Stern auf dem Bildschirm hinterlassen. Was hier gleich auffällt, dass das Hauptprogramm nur aus einer Leerschleife besteht. Dies ist typisch für moderne Oberflächen. Der komplette Programmablauf findet nur über die Bildschirmsteuerung statt. Wie dies genau geschieht, werden wir im Laufe des Lehrgang noch sehen. Daher gibt es auch eine Zeilenlücke zwischen 60170 und 60490. Hier findet später die Auswertung der Bildschirmelemente statt.

 

 

Die wohl wichtigsten Elemente: Die Schaltflächen

 

Um die Struktur der einzelnen Objekte auf unserer Oberfläche darzustellen, binden wir als Erstes erst einmal einfache Schaltflächen ein. Diese können in unserem Demo-Programm angewählt werden und zeigen in diesem Fall einen kleinen Text in der ersten Bildschirmzeile.

 

Hierfür muss das Mausprogramm natürlich um die entsprechenden Routinen erweitert werden, wie das folgende Demo-Programm zeigt:

 

  10 REM ********************
20 REM **   BeetleGUI    **
30 REM **    (C) 2012    **
40 REM ** Thomas Krueger **
50 REM ********************
60 REM
70 GOSUB 60000:' Initialisierung der GUI
100 X=2:Y=24:CAP$="Button 1":ACT=LINEPOS(10000): GOSUB 61000
110 X=70:Y=24:CAP$="Button 2":ACT=LINEPOS(20000): GOSUB 61000
1000 DO:LOOP
10000 REM *** Ereignis-Prozedur: Button 1 ***
10010 X=35:Y=1: GOSUB 65515:PRINT "Button 1 betaetigt";:RETURN
20000 REM *** Ereignis-Prozedur: Button 2 ***
20010 X=35:Y=1: GOSUB 65515:PRINT "Button 2 betaetigt";:RETURN
60000 REM *****************************
60010 REM ** Initialisierung der GUI **
60020 REM *****************************
60030 REM
60040 DIM JX,JY,K$*1,COL,X,Y,XL,YH,CAP$*40,STATE,ACT,C1,C2,C3,C4
60050 DIM OID&(63),OX&(63),OY&(63),OL&(63),OH&(63),OCAP$(63)*40,OSTATE(63)
60060 DIM OACT(63),OMAX
60080 CLS:PRINT CHR$(20);:JX=40:JY=12: GOSUB 65505:OMAX=0
60090 EVERY 10,3 GOSUB 60100:RETURN
60100 REM *** Tastaturabfrage und Auswertung ***
60110 K$=INKEY$:IF K$="" THEN RETURN
60120 SELECT ASC(K$)
60130 CASE 224:IF JY>1 THEN DEC JY:GOSUB 65505:RETURN
60140 CASE 225:IF JX<80 THEN INC JX:GOSUB 65505:RETURN
60150 CASE 226:IF JY<25 THEN INC JY:GOSUB 65505:RETURN
60160 CASE 227:IF JX>1 THEN DEC JX:GOSUB 65505:RETURN
60170 CASE 13: GOTO 60200
60180 CASEELSE:RETURN
60190 REM *** Auswertung des Maus-Cursors ***
60200 IFF OMAX THEN RETURN
60210 FOR C2=0 TO OMAX:C1=OMAX-C2-1
60220 IF (JY<OY&(C1)) OR (JY>(OY&(C1)+OH&(C1)-1)) THEN GOTO 60250
60230 IF (JX<OX&(C1)) OR (JX>(OX&(C1)+OL&(C1)-1)) THEN GOTO 60250
60240 BREAK 60270
60250 NEXT:RETURN
60260 REM *** Objekt identifiziert. Ereignis ausloesen ***
60270 SUBDIR OACT(C1):COL=7: GOSUB 65525: GOTO 65505
61000 REM ******************************
61010 REM ** Buttons: Initialisierung **
61020 REM ******************************
61030 REM
61040 OID&(OMAX)=1:OX&(OMAX)=X:OY&(OMAX)=Y:OL&(OMAX)=2+LEN(CAP$)
61050 OH&(OMAX)=1:OCAP$(OMAX)=CAP$:OACT(OMAX)=ACT:C1=OMAX:INC OMAX
61060 GOSUB 61100:COL=7: GOSUB 65525: GOSUB 65505:RETURN
61100 COL=&HE4: GOSUB 65525:X=OX&(C1):Y=OY&(C1): GOSUB 65515
61110 PRINT " ";OCAP$(C1);" ";:RETURN
65500 REM ************************
65501 REM ** Maus-Cursor setzen **
65502 REM ************************
65503 REM
65505 PRINT CHR$(27);"[";STR$(JY-1);";";STR$(JX-1);"H";:RETURN
65510 REM ************************
65511 REM ** Text-Cursor setzen **
65512 REM ************************
65513 REM
65515 PRINT CHR$(27);"[";STR$(Y-1);";"STR$(X-1);"H";:RETURN
65520 REM ***************************************
65521 REM ** Textfarbe und Hintergrund aendern **
65522 REM ***************************************
65523 REM
65525 IF (COL AND 128) THEN PRINT CHR$(27);"[4m"; ELSE PRINT CHR$(27);"[6m";
65526 PRINT CHR$(27);"[4";STR$((COL SHR 4) AND 7);"m";
65527 IF (COL AND 8) THEN PRINT CHR$(27);"[1m"; ELSE PRINT CHR$(27);"[2m";
65528 PRINT CHR$(27);"[3";STR$(COL AND 7);"m";
65529 RETURN

 

Um entsprechende Objekte in so einer Oberfläche einzubinden, müssen diese erst einmal im System angemeldet werden. Wir verwenden hier 2 Schaltflächen. Diese werden in den beiden folgenden Zeilen angemeldet:

 

 

...

100 X=2:Y=24:CAP$="Button 1":ACT=LINEPOS(10000): GOSUB 61000
110 X=70:Y=24:CAP$="Button 2":ACT=LINEPOS(20000): GOSUB 61000
...

 

Hier werden die Position, die Beschriftung und die Programmzeile übergeben, die den Code enthält, welches dem Rechner sagt, was er tun soll, wenn die Schaltfläche betätigt wird. Als nächstes muss die Initialisierungsroutine aufgerufen werden. Diese sorgt dafür, dass die Schaltflächen entsprechend überwacht werden und bei Betätigung der entsprechende Code aufgerufen wird.

 

Schauen wir uns diese Initialisierungsroutine einmal näher an:

 

  ...
61000 REM ******************************
61010 REM ** Buttons: Initialisierung **
61020 REM ******************************
61030 REM
61040 GOSUB 61100:OID&(OMAX)=1:OX&(OMAX)=X:OY&(OMAX)=Y:OL&(OMAX)=2+LEN(CAP$)
61050 OH&(OMAX)=1:OCAP$(OMAX)=CAP$:OACT(OMAX)=ACT:C1=OMAX:INC OMAX
61060 COL=7: GOSUB 65525: GOSUB 65505:RETURN
61100 COL=&HE4: GOSUB 65525:X=OX&(C1):Y=OY&(C1): GOSUB 65515
61110 PRINT " ";OCAP$(C1);" ";:RETURN
...

 

Zu Beginn wird die Schaltfläche gezeichnet, welches in der Unterroutine in Zeile 61100 geschieht. Für den Kenner dürfte die Funktion recht leicht zu erkennen sein. Mit COL=&HE4 und dem darauf folgenden GOSUB legen wir türkis als Hintergrund mit blauer Schrift fest. Dann wird die gewünschte Schaltflächenposition angesprungen. X und Y sind ja bereits gesetzt, daher ist eine Zuweisung hier nicht nötig. Dann muss die Schaltfläche nur noch gezeichnet werden, welches der PRINT-Befehl besorgt.

 

In der Zeile 61040 und 61050 werden als erstes die ganzen Parameter in die Variablenfelder für die Objektverwaltung übernommen. Für die spätere Verwendung müssen wir im Variablenfeld noch eine ID festlegen, damit die Objektverwaltung später weiß, dass es sich hier um Schaltflächen handelt. Der Rest ist im Grunde nur reines kopieren. Schaltflächen sind immer 2 Zeichen länger als der Text, somit wird OL die Textlänge plus 2 zugewiesen. Und da Schaltflächen immer 1 Zeichen hoch sind, ist OH hier auch 1. Anschließend wird noch der Objektzähler erhöht, welcher dem System mitteilt, wie viel Objekte es zur Zeit gibt.

 

Zum Schluss wird noch die Mauscursor-Position und Farbe wieder hergestellt und zum Hauptprogramm zurück gekehrt.

 

Nun wurden die Schaltflächen angemeldet und es muss nichts weiter getan werden. Daher auch die Leerschleife in Zeile 1000. Wird nun eine der beiden Schaltflächen bedient, so erkennt dies die Auswerteroutine, welche wir ab Zeile 60200 eingefügt haben. Die Routine wird aufgerufen, sobald die [ENTER]-Taste betätigt wird. Diese Routine betrachten wir natürlich auch einmal etwas näher:

 

  ...
60190 REM *** Auswertung des Maus-Cursors ***
60200 IFF OMAX THEN RETURN
60210 FOR C2=0 TO OMAX:C1=OMAX-C2-1
60220 IF (JY<OY&(C1)) OR (JY>(OY&(C1)+OH&(C1)-1)) THEN GOTO 60250
60230 IF (JX<OX&(C1)) OR (JX>(OX&(C1)+OL&(C1)-1)) THEN GOTO 60250
60240 BREAK 60270
60250 NEXT:RETURN
60260 REM *** Objekt identifiziert. Ereignis ausloesen ***
60270 SUBDIR OACT(C1):COL=7: GOSUB 65525: GOTO 65505
...

 

In 60200 überprüfen wir überhaupt erst einmal, ob irgendwelche Objekte zur Überwachung vorhanden sind. Ist dies nicht der Fall (OMAX=0) wird die Auswertung gleich wieder verlassen.

 

Wir haben aber nun 2 Schaltflächen definiert und so startet eine FOR-NEXT-Schleife welche alle vorhanden Objekte abfragt, ob diese evtl. unter dem Mauscursor liegen. Hierfür werden einfach 2 IF-Anweisungen verwendet. Befindet sich der Mauscursor außerhalb des Objektes, wird die weitere Prüfung unterlassen und das nächste Objekt geprüft. Wurden alle Objekte ergebnislos geprüft, so wird die Routine verlassen.

 

Befindet sich das Objekt jedoch unterhalb des Mauscursors, so wird die FOR-NEXT-Schleife verlassen damit ein Ereignis ausgelöst werden kann. Das Ereignis lösen wir einfach aus, indem der SUBDIR-Befehl ausgeführt wird, welche unsere vorher definierte Routine aufruft. In unserem Fall ab Zeile 10000 oder 20000. Wurde die Funktion des entsprechenden Objektes mit dem RETURN-Befehl beendet, wird die Standard-Farbe und die alte Maus-Position wieder hergestellt. Letztere sorgt auch gleichzeitig dafür, dass die Auswerte-Routine gleich verlassen wird.

 

Aus logischen Gründen müssen wir die Objekte vom letzten zum ersten definierten Objekt abfragen. Warum dies so ist, werden wir bei späteren Objekten noch erfahren.

 

Das Ganze sieht dann schon ganz nett aus:

 

Klicken für Originalgröße

 

 

Check'st du's: Die Checkboxen

 

Neben den Schaltflächen sind noch weitere Bedienelemente notwendig um ein Programm vernünftig führen zu können. Unter anderem werden hier auch noch so genannte Checkboxen verwendet. Diese Elemente ermöglichen es, bestimmte Optionen zu aktivieren oder eben auch zu deaktivieren.

 

Damit unser System wieder weiß, dass Checkboxen verwendet werden sollen, müssen diese erst einmal angemeldet werden:

 

 

...

100 X=23:Y=12:CAP$="Ich finde den BasicBeetle gut"
105 ACT=LINEPOS(10000):STATE=FALSE:GOSUB 61200
110 X=35:Y=24:CAP$="Demoende":ACT=LINEPOS(20000): GOSUB 61000
...

 

Die Anmeldung findet hier in den Zeilen 100 und 105 statt. Neben der Position (X, Y) wird auch die Beschriftung und wieder die Zeilennummer übergeben, welche dem System sagt, wo er die Zeile findet, die angesprungen wird, wenn die Checkbox betätigt wird.

 

Gegenüber einer Schaltfläche gibt es hier aber schon die erste Neuerung. Es wird der aktuelle Status mit übergeben durch die Zuweisung der Variablen STATE. Dadurch kann eine eventuell schon früher aktivierte Checkbox wieder entsprechend angezeigt werden.

 

Nach Aufruf der Unterroutine ab Zeile 61200 erscheint dann auf dem Display das neue Element:

 

 

[ ] Ich finde den BasicBeetle gut

 

In Zeile 110 definieren wir noch eine Schaltfläche, die das Demoprogramm beendet.

 

Über die Ereignisroutine für die Checkbox und der Schaltfläche muss wohl nicht viel gesagt werden. Wir müssen diese aber dennoch ins Programm einfügen:

 

 

...

10000 REM *** Check-Box: Auswertung ***
10010 X=32:Y=1: GOSUB 65515:PRINT "Check-Box ";
10020 IF STATE THEN PRINT "aktiv "; ELSE PRINT "inaktiv";
10030 RETURN
20000 REM *** Button: Auswertung ***
20010 COL=7: GOSUB 65525:CLS:END
...

 

Interessant wird es erst wieder ab der Zeile 61200 ab der wir die Checkbox einrichten und darstellen:

 

 

...

61200 REM **********************************
61210 REM ** Check-Boxen: Initialisierung **
61220 REM **********************************
61230 REM
61240 GOSUB 61300:OID&(OMAX)=2:OX&(OMAX)=X:OY&(OMAX)=Y:OL&(OMAX)=4+LEN(CAP$)
61250 OH&(OMAX)=1:OCAP$(OMAX)=CAP$:OACT(OMAX)=ACT:OSTATE(OMAX)=STATE
61260 C1=OMAX:INC OMAX: GOSUB 61310:COL=7: GOSUB 65525: GOSUB 65505:RETURN
61300 COL=&HE4: GOSUB 65525: GOSUB 65515:PRINT "[ ] ";CAP$;:RETURN
61310 COL=&HE4: GOSUB 65525:X=OX&(C1)+1:Y=OY&(C1): GOSUB 65515
61320 SELECT OSTATE(C1)
61330 CASE FALSE:PRINT " "
61340 CASE TRUE:PRINT "X"
61350 COL=7: GOSUB 65525: GOSUB 65505:STATE=OSTATE(C1):RETURN
...

 

Wie auch schon bei der Schaltfläche, werden hier die Parameter in das Variablenfeld übernommen. Die Darstellungsroutine ab Zeile 61300 ist hier aber ein wenig komplizierter. In Zeile 61300 wird die eigentliche Check-Box gezeigt. Dieses muss nur einmal, bei der Darstellung getan werden. Da sich dieses Element aber bei Bedienung ändert, gibt es noch eine weitere Routine ab 61310. Je nach neuem Status, wird hier nun ein 'X' gesetzt bzw. wieder gelöscht.

 

Das anschließend die Standardfarbe und die alte Maus-Position wieder hergestellt wird, sollte wohl selbstverständlich sein.

 

 

...

60260 REM *** Objekt identifiziert. Ereignis ausloesen ***
60270 SELECT OID&(C1)
60280 CASE 2:OSTATE(C1)=NOT(OSTATE(C1)): GOSUB 61310
60900 IF OACT(C1) THEN SUBDIR OACT(C1):COL=7: GOSUB 65525: GOTO 65505
60910 RETURN
...

 

Gegenüber der Schaltfläche müssen wir nun auch dafür sorgen, dass sich die Darstellung der Check-Box ändert, wenn diese bedient wird. Hierzu reicht es nun nicht mehr aus, die vorher definierte Ereignisroutine (Zeile 10000 ff.) aufzurufen. Es muss gleichzeitig noch das Aktualisierungs-Unterprogramm ab Zeile 61310 aufgerufen werden. Und hier wird nun das erste mal die Objekt-ID, die wir bei unseren beiden Bedienelementen mit definiert haben, wichtig. Hierdurch kann der Manager erkennen, welche Routine er anspringen muss, um das Bedienelement zu aktualisieren.

 

Die Erkennung des entsprechenden Elements ist ja nicht sonderlich schwer. Mit Hilfe des Select-Befehls in Zeile 60270 stellen wir die aktuelle ID fest. 60280 erkennt dann, dass es sich um eine Checkbox handelt. Es wird dann erst der Status geändert. Also eine nicht aktive Checkbox wird aktiviert und umgekehrt und dann dafür gesorgt, dass dieser neue Status auch angezeigt wird.

 

Anschließend folgt, wie schon bereits bekannt, der Aufruf der Ereignisroutine. Das Ganze sieht dann so aus:

 

Klicken für Originalgröße

 

 

Radio-Buttons - Schalt mich um

 

Soll ein Benutzer die Möglichkeit haben, einen aus mehreren Optionen auszuwählen, so verwendet man so genannte Radio-Buttons. Diese Bezeichnung stammt von den früheren Radios, bei denen die einzelnen Frequenzbänder mit Schaltern umschaltbar waren. Hierbei sprang ein gedrückter Schalter wieder raus, wenn ein anderes Band gewählt wurde. Ähnlich funktionieren auch die Radio-Buttons hier. Wählt man eine andere Option so wird der bereits gewählte deaktiviert.

 

Radio-Buttons haben aber einige besondere Eigenschaften gegenüber den bisher vorgestellten Elementen. Zum Einen wurde es ja schon erwähnt, dass sich mehrere Radio-Buttons gegenseitig beeinflussen. Aber um dies zu können, muss man diese zu einer Gruppe zusammen fassen. Dazu wird erst noch ein 'Container' benötigt der den Buttons sagt, dass diese zusammen gehören.

 

Bevor es zu theoretisch wird, schauen wir uns erst einmal die Definition an:

 

 

...

100 X=24:Y=10:XL=30:YH=5:CAP$="Wie geht es dir?": GOSUB 61400
110 X=26:Y=11:CAP$="Froehlich":STATE=FALSE: GOSUB 61600
120 X=26:Y=12:CAP$="Traurig ":STATE=FALSE: GOSUB 61600
130 X=26:Y=13:CAP$="Wuetend ":STATE=FALSE: GOSUB 61600
200 X=35:Y=24:CAP$="Demoende":ACT=LINEPOS(20000): GOSUB 61000
...

 

In Zeile 100 wird zunächst das Container-Element definiert. Alle nachfolgenden Radio-Elemente gehören nun zu diesem Container bis eventuell ein weiterer Container definiert wird.

 

In 110-130 werden nun mehrere Radio-Buttons gestartet. In diesem Demo verzichten wir auf eine Ereignisauswertung mit Hilfe der ACT-Variable. Wird diese aber benötigt, um zum Beispiel, direkt beim Umschalten eine Aktion auszulösen, kann diese zugewiesen werden.

 

Zum Schluss wird noch eine einfache Schaltfläche initialisiert um unser Demo beenden zu können.

 

Der Container tut im Grunde nichts weiter. Es muss nur ein entsprechendes Element auf dem Terminal gezeichnet werden. Ansonston hat der Container keine weitere Funktion. Das Zeichnen übernimmt hier die Routine ab der Zeile 61400:

 

 

...

61400 REM ******************************
61410 REM ** Container initialisieren **
61420 REM ******************************
61430 REM
61450 OID&(OMAX)=3:OX&(OMAX)=X:OY&(OMAX)=Y:OL&(OMAX)=XL:OH&(OMAX)=YH
61460 OCAP$(OMAX)=CAP$:INC OMAX:C1=OMAX-1: GOSUB 61500
61470 COL=7: GOSUB 65525: GOSUB 65505:RETURN
61500 COL=&HE4: GOSUB 65525:X=OX&(C1):Y=OY&(C1): GOSUB 65515
61510 PRINT CHR$(218);STRING$(OL&(C1)-2,196);CHR$(191);
61520 FOR Y=OY&(C1)+1 TO OY&(C1)+OH&(C1)-2
61530 GOSUB 65515:PRINT CHR$(179);STRING$(OL&(C1)-2," ");CHR$(179);:NEXT
61540 INC Y:GOSUB 65515:PRINT CHR$(192);STRING$(OL&(C1)-2,196);CHR$(217);
61550 X=OX&(C1)+1:Y=OY&(C1): GOSUB 65515:PRINT " ";OCAP$(C1);" ";
61560 RETURN
...

 

Auch die Radio's müssen, wie üblich, initialisiert werden, welches die Routine ab der Zeile 61600 übernimmt:

 

 

...

61600 REM *********************************
61610 REM ** Radio-Button initialisieren **
61620 REM *********************************
61630 REM
61640 GOSUB 61670:OID&(OMAX)=4:OX&(OMAX)=X:OY&(OMAX)=Y:OL&(OMAX)=4+LEN(CAP$)
61650 OH&(OMAX)=1:OCAP$(OMAX)=CAP$:OACT(OMAX)=ACT:OSTATE(OMAX)=STATE:INC OMAX
61660 C1=OMAX-1: GOSUB 61310:COL=7: GOSUB 65525: GOSUB 65505:RETURN
61670 COL=&HE4: GOSUB 65525: GOSUB 65515:PRINT "( ) ";CAP$;:RETURN

...

 

Interessant wird es erst bei der Auswertung:

 

 

...

61700 C3=C1:DO:IF OID&(C3)=3 THEN BREAK 61710 ELSE DEC C3:LOOP
61710 INC C3:C4=C3:DO:OSTATE(C3)=FALSE:INC C3:WHILE OID&(C3)=4:DEC C3
61720 OSTATE(C1)=TRUE:COL=&HE4: GOSUB 65525
61730 FOR C2=C4 TO C3:X=OX&(C2)+1:Y=OY&(C2): GOSUB 65515
61740 IF OSTATE(C2) THEN PRINT "*"; ELSE PRINT " ";
61750 NEXT:COL=7: GOSUB 65525: GOSUB 65505:RETURN
...

 

Als erstes wird hier das Container-Element gesucht (Zeile 61700). Diese wird durch die ID von 3 erkannt. Als Nächstes werden alle die Elemente nach dem Container abgesucht, ob diese Radio-Buttons sind. Und auch gleichzeitig deaktiviert.

 

Wurden alle, zu dem Container gehörenden, Radio-Elemente gefunden, so wird das Angeklickte wieder aktiviert (Zeile 61720). Anschließend werden sämtliche Radio-Buttons noch auf dem Display aktualisiert.

 

Zum Schluss noch ein Screenshot der Radio-Buttons:

 

Klicken für Originalgröße

 

 

Fortsetzung folgt ...

 

 

Zurück zur Startseite          Zurück zur Auswahl