Den Anwendern von Mal- und Zeichenprogrammen ist die UNDO-Funktion, die mit der gleichnamigen Taste des Atari ST ausgelöst wird, wohlbekannt: Diese Taste ermöglicht es, die zuletzt ausgeführte graphische Funktion auf dem Bildschirm rückgängig zu machen. Damit können Bilder gerettet werden, die sonst, z.B. durch ein falsches Füllmuster oder eine falsch positionierte Linie, verloren wären.
In diesem Artikel werden die Grundlagen der Programmierung einer universellen UNDO-Routine in GFA-BASIC dargestellt. Bei der Entwicklung dieser Routine bildete die Programmierung einer mausgesteuerten Notenedition den Ausgangspunkt. Die Positionierung von Noten auf dem Bildschirm mittels Maus ist an sich eine komfortable Vorgehensweise. Aufgrund der Vielfalt der graphischen Symbole sowie der äußerst engen räumlichen Abstände sind Eingabefehler jedoch kaum zu vermeiden. Derartige Fehler können mit der UNDO-Routine problemlos korrigiert werden. Die vorgestellte Routine ist dabei ohne weiteres auf andere Programme, innerhalb derer graphische Symbole auf engem Raum positioniert werden, übertragbar.
Da das folgende Programmlisting lediglich Beispielcharakter haben soll, wird die Funktionsweise der UNDO-Routine hier im Rahmen einer einfachen Graphik-Prozedur demonstriert. In dieser Prozedur können Noten an beliebiger Stelle in einem Notensystem positioniert werden.
Das Prinzip der UNDO-Funktion besteht darin, jeweils vor der nächsten Ausführung eines graphischen Befehls den Bildschirm komplett zu retten, d.h. zu speichern. Im Falle eines Eingabefehlers wird dann das neue, fehlerhafte Bild einfach durch das alte, fehlerfreie Bild ersetzt.
Da in der UNDO-Routine nicht ein Bildschirmausschnitt, sondern immer der komplette Bildschirm - einschließlich Menüleiste - gespeichert wird, bieten sich für diesen Zweck die sehr schnellen Befehle SGET und SPUT des GFA-BASIC an.
Der mit SGET in einer Stringvariablen gespeicherte Bildschirminhalt wird mit dem SPUT-Befehl in den Bildschirmspeicher transportiert. Sein alter Inhalt wird dabei überschrieben, so daß der fehlerhafte Bildschirm innerhalb der UNDO-Routine nicht mit CLS gelöscht zu werden braucht - SPUT erledigt diese Aufgabe automatisch.
Es sind drei Problemstellungen zu lösen:
Es wird davon ausgegangen, daß das Listing in einem Programm mit Desktop-Menü und GEM-Fenstern verwendet wird.
Für den Fall, daß die UNDO-Taste versehentlich vor dem ersten Mausklick betätigt wird, muß zunächst die Variable >Bild$< durch >Sget Bild$< gefüllt werden. Träfe nämlich der Befehl >Sput Bild$< auf eine noch nicht definierte Variable, wäre eine 2-Bomben-Fehlermeldung die unangenehme Folge.
In einer >Do-Loop<- Hauptschleife befindet sich die eigentliche UNDO-Schleife. Bis zur Betätigung einer Maustaste findet in dieser Schleife die Abfrage der UNDO-Taste mit >If Inkey$ = Chr$(0) + Chr$(97) < statt.
Wird die Prozedur in einem Programm mit Desktop-Menü und GEM-Fenster eingesetzt, ist folgendes zu berücksichtigen: Wenn in der UNDO-Schleife Ereignisüberwachung und Tastaturabfrage nicht getrennt sind, äußert sich dies in der Weise, daß die UNDO-Taste mit zeitlicher Verzögerung “anspricht". Deshalb wird durch eine Bedingungsabfrage sichergestellt, daß nur dann, wenn der Mauszeiger den Bereich der Menü-Titelzeile betritt, die Ereignisüberwachung mit >On menu< eingeschaltet wird. Hierbei ist noch zu bemerken, daß für die Y-Mauskoordinate oberhalb des Arbeitsbereichs - also im Bereich von Infozeile, Titelzeile und Menütitelzeile - Werte von 65498 bis 65534 zurückgegeben werden. Aufgrund dieses Kuriosums ist der Graphikfenster-Bereich durch Y%-Werte >30 und <399 eingegrenzt.
Erfolgt jetzt im Programm ein Mausklick mit der linken oder rechten Taste, wird die UNDO-Schleife verlassen. Für graphische Funktionen ist es im Hinblick auf die Ökonomie des Listings sinnvoll, die horizontale und vertikale Mauskoordinate sowie den Status der Maustasten mit >Mouse< den Variablen X%,Y% und K% zuzuordnen. Diese Variablen werden in die folgenden Graphikbefehle >Pellipse< und >Line< eingebunden. Unmittelbar bevor nun mit diesen Befehlen eine einzelne Note auf dem Bildschirm plaziert wird, findet mit >Sget Bild$< die Speicherung des noch nicht veränderten Bildschirms statt. Die Richtung des Notenhals wird dabei mit der linken Maustaste (Hals nach oben) bzw. der rechte Taste(Hals nach unten) bestimmt.
Danach verbleibt das Programm bei gedrückter Maustaste in einer Warteschleife. Damit ist gewährleistet, daß pro Mausklick die Graphikbefehle >Pellipse< und >Line< nur einmal ausgeführt werden, d.h. pro Mausklick genau eine Note gezeichnet wird. Nach dem Loslassen der Maustaste gelangt das Programm aus der Do-Loop-Hauptschleife wieder zurück in die UNDO-Schleife. Jetzt kann mit Betätigung der UNDO-Taste die letzte Bildschirmveränderung zurückgenommen, bzw. mit erneutem Mausklick die nächste Note positioniert werden.
Die UNDO-Routine kann in der gezeigten Form unverändert in weitere Prozeduren eines Programms übernommen werden. Sofern sich diese graphischen Prozeduren auf den gleichen Bildschirm beziehen, kann der SGET-Befehl auch mit der gleichen Variablen - im Programmbeispiel >Bild$< - verknüpft werden. Auf diese Weise wird der Speicherbedarf der UNDO-Funktion im gesamten Programm auf 32 kByte begrenzt.
Dim M$(17) !Menü erstellen
Restore Mmenue
For Z%=0 To 16
Read M$(Z%)
Next Z%
Mmenue:
Data DESK , UNDODEMO,-----------------------
Data 1,2,3,4,5.6.""
Data NOTEN , Zeichnen,-------------------, Quit,"","",""
Menu M$()
Titlew 1," UNDODEMO " !GEM-Fenster
Fullw 1 !öffnen
'
Gosub Menu
Procedure Menu
Do !Auf Ereignis
On Menu !warten
On Menu Gosub Auswahl !und verzweigen
Loop
Return
'
Procedure Auswahl !Auswahl treffen
Do
If Menu(0)=1
Menu Off
Gosub Copyright
Endif
If Menu(0)=11
Menu Off
Gosub Noten !Noten zeichnen
Endif
If Menu(0)=13
Menu Off
End !Ende
Endif
Loop
Return
'
' **** UNDO-Demo ****
'
Procedure Noten
Gosub Noten_system
Sget Bild$
Do
While Mousek=0 !UNDO-Schleife
If Inkey$=Chr$(0)+Chr$(97) !Wenn UNDO-Taste gedrückt
Sput Bild$ !Bildschirmspeicher erneuern
Endif
If Mousey<30 Or Mousey>399 !Maus in Titelzeile?
On Menu
Endif
Wend
Mouse X%,Y%,K%
If K%=1 And Y%>30 And Y%<399 !Linke Maustaste gedrückt?
Sget Bild$ !Altes Bild retten
Pellipse X%,Y%,5,3 !Notenkopf und
Line X%+5,Y%,X%*5,Y%-15 !Notenhals (nach oben) zeichnen
Endif
If K%=2 And Y%>30 And Y%<399 !Rechte Maustaste gedrückt?
Sget Bild$ !Altes Bild retten
Pellipse X%,Y%,5,3 !Notenkopf und
Line X%-5,Y%,X%-5,Y%+15 !-hals (nach unten) zeichnen
Endif
While Mousek<>0 !Warteschleife
Wend
Loop
Return
'
Procedure Noten_system !Zeichnet Notenlinien
Cls
Local Z%
Y0%=100
For Z%=0 To 4
Line 50,Y0%+6*Z%,550,Y0%+6*Z%
Next Z%
Return
'
Procedure Copyright
Cls
Box 190,70,420,270
Deftext ,,,26
Text 200,130,"UNDO-Routinen"
Deftext ,,,13
Text 260,170,"in GFA-Basic"
Deftext ,,,6
Text 220,210,"von Hans-H.Ackermann"
Gosub Menu
Return