UNDO-Routinen in GFA-BASIC

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.

Prinzip

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.

SGET und SPUT

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.

Realisierung

Es sind drei Problemstellungen zu lösen:

  1. Der SGET-Befehl darf nur unmittelbar vor einem Graphik-Befehl ausgeführt werden, da andernfalls eine ordnungsgemäße UNDO-Funktion nicht gewährleistet ist.
  2. In Programmmen mit Desktop-Menü müssen UNDO-Tastenabfrage und On Menü-Ereignisüberwachung voneinander getrennt werden, weil sonst die UNDO-Funktion durch zeitliche Verzögerungen beeinträchtigt wird.
  3. Der Graphikbefehl soll nur einmal pro Mausklick ausgeführt werden.

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

Hans-H. Ackermann
Aus: ST-Computer 07 / 1988, Seite 88

Links

Copyright-Bestimmungen: siehe Über diese Seite