← ST-Computer 03 / 1989

Variable Bildausschnitte (GFA)

Programmierpraxis

Jedes anspruchsvolle Mal- und Grafikprogramm verfügt über eine Funktion, die es gestattet. Bildausschnitte von beliebiger Größe auf dem Bildschirm zu verschieben bzw. zu kopieren. Hierbei besteht der Unterschied zwischen „Verschieben“ und „Kopieren“ darin, daß bei der Funktion „Verschieben“ der Ausschnitt im wahrsten Sinne aus dem Bild „herausgeschnitten“ wird. Bei der Funktion „Kopieren“ verbleibt der Originalausschnitt im Bild, die Kopie des Ausschnitts läßt sich an anderer Stelle beliebig positionieren.

Das Verschieben von grafischen Einheiten stellt den wesentlichen Bestandteil des sogenannten Layouts etwa einer Druckvorlage dar. Die in diesem Artikel gezeigten Routinen lassen Schere und Klebstoff - Hauptwerkzeuge beim Layout - endgültig überflüssig werden: Alle grafischen Einheiten, seien es Texte, Bilder oder auch Notensysteme, können mit der Maus auf dem Bildschirm druckfertig arrangiert werden.

Das Prinzip

Der zu verschiebende Bildausschnitt wird mit dem „Gummifaden“ eingerahmt. Dieser eingerahmte Bildschirmbereich wird in geeigneter Weise zwischengespeichert - gepuffert - und kann dann an beliebiger Stelle mit der Maus wieder auf dem Bildschirm plaziert werden. Bei der Funktion „Verschieben“ wird der Bereich unter dem Rahmen gelöscht.

Die Realisierung

Die Realisierung dieses an sich einfachen Prinzips findet sich in der Procedure Verschieben(Copy%). Betrachten wir das Listing:

Die Do-Loop-Hauptschleife ist nur notwendig, falls nach dem Aufruf der Prozedur die Möglichkeit bestehen soll, mehrere Verschiebungen unmittelbar nacheinander vornehmen zu können.

Die erste While-Wend-Schleife wird bis zum Mausklick mit der linken Taste durchlaufen. Dabei ist die Menüüberwachung eingeschaltet. Erfolgt nun ein Mausklick, wird mit MOUSE xl%, yl%,k% die augenblickliche Bildschirmposition der Maus festgehalten und der Variablen xl% bzw. yl% übergeben.

Der Rahmen

Die Werte der Koordinaten xl% und yl% bleiben in der nun folgenden Rahmenschleife konstant, da hier mit MOUSE xr%,yr%,k% eine eigene Mausstatusauswertung erfolgt. Der Grund für diese zweifache Statusermittlung liegt in dem Prinzip, nach dem der “Gummifaden” auf dem Bildschirm erzeugt wird: Für das Zeichnen des Rahmens mit dem BOX-Befehl werden vier Koordinaten benötigt, zwei für die linke obere Ecke (xl%,yl%) und zwei für die rechte untere Ecke (xr%,yr%). Da die Größe des Rahmens mit der Maus eingestellt wird und diese nur zwei Koordinaten liefert, müssen die Werte der linken, oberen Koordinaten konstant bleiben, wahrend die Werte der Koordinaten der rechten, unteren

Ecke analog zur Mausbewegung verändert werden können. Zur Realisierung des “Gummifadens' benötigt man demnach prinzipiell zwei Schleifen mit zwei unabhängigen Statusermittlungen.

Nach einer Bewegung der Maus muß vor dem Zeichnen des neuen Rahmens der alte Rahmen gelöscht werden, da andernfalls nach mehreren Mausbewegungen nur noch ein schwarz ausgefülltes Rechteck auf dem Bildschirm verbleiben würde. Das Löschen das alten Rahmens geschieht mit dem zweiten BOX-Befehl innerhalb der Rahmenschleife. Die beiden gleichartigen BOX-Befehle sind durch eine Repeat-Until-Schleife voneinander getrennt. Diese Schleife wird nach einer Mausbewegung verlassen, und das zweite BOX xl%,yl%,xr%,yr% überschreibt (im Graphmode 3) den alten Rahmen.

Die Rahmenschleife wird verlassen, sobald die linke Maustaste losgelassen wurde. Der eingerahmte Bereich wird jetzt mit GET xl%,yl%,xr%,yr%,Snp$ gepuffert. Findet die Verschiebung/Kopie in einem GEM-Fenster statt, muß zur y-Koordinate der Wert 38 hinzuaddiert werden. Der Grund hierfür: Die Grafikbefehle in GEM-Fenstern haben einen anderen Bezugspunkt als die Rasterbefehle GET und PUT, die immer vom Punkt (0,0) ausgehen.

Soll der Ausschnitt verschoben, aber dabei nicht kopiert werden, überdeckt ein Rechteck von der Größe des Ausschnitts den eingerahmten Bereich mit PBOX xl%,yl%,xr%,yr% bei Deffill 0. Die Füllmusterfarbe wird danach sicherheitshalber mit Deffill 1 wieder auf "Objektfarbe” festgelegt. Die Entscheidung, ob der Ausschnitt verschoben oder kopiert wird, übergibt man schon beim Aufruf der Prozedur mit dem Wert der Variablen Copy%. Nach dem Verlassen der Rahmenschleife würde sich ohne weitere Maßnahmen der Mauscursor an der rechten unteren Ecke des Rahmens befinden. Damit in der folgenden Verschiebeschleife der Mauscursor sofort wieder an der linken oberen Ecke des Ausschnitts erscheint, wird mit DPOKE 9952,xl%+1 bzw. DPOKE 9954,yl%+38 der Cursor dorthin zurückgesetzt. Eine beliebige Mausposition kann also bestimmt werden, indem einfach die entsprechenden Werte plus GEM-Offset an diese Adressen ge” de poked” werden.

Verschieben und Kopieren

In der Verschiebeschleife wird nach erneuter Statusermittlung zunächst der Originalhintergrund mit SGET Bild$ gepuffert. Nun zeigt PUT x%,y%+38,Snp$,7 den Ausschnitt, was allerdings erst ab dem zweiten Schleifendurchlauf, d.h. nach der ersten Verschiebung, deutlich wird: Nach einer Mausbewegung wird die While-Wend-Warteschleife verlassen und mit SPUTBild> der Ausschnitt an seiner alten Position überdeckt. Die Verschiebeschleife wird erneut durchlaufen, und jetzt zeigt der PUT-Befehl den Ausschnitt an seiner neuen Position.

Erfolgt nun ein abschließender Mausklick, wird die Verschiebeschleife verlassen, und der Ausschnitt befindet sich an seiner endgültigen Position.

Die Möglichkeit zum Verschieben des Ausschnitts resultiert demnach aus dem Zusammenwirken der Befehle SPUT für den Hintergrund und PUT für den Ausschnitt. Die Tatsache, daß der Ausschnitt nach einer Mausbewegung an seiner alten Position mit SPUT überdeckt wird, ist übrigens die Ursache für ein leichtes Flackern des Ausschnitts während des Verschiebens. Die Warteschleife sorgt dafür, daß bei unbewegter Maus kein solches Flackern entsteht. Für den jeweiligen PUT-Modus stehen prinzipiell die Werte 0 bis 15 zur Verfügung, wobei die wichtigsten die Modi 3 (Graphmode 1), 6 (Graphmode 3), 7 (Graphmode 2) und 4 (Graphmode 4) sind.

Die beschriebene Prozedur kann in jedes Grafikprogramm integriert werden. In dieser Demoversion werden mit der Procedure Flaechen bzw. Procedure Text einfache grafische Einheiten zum Ausprobieren der Verschiebe- bzw. Kopierfunktion erzeugt.

' (c) MAXON Computer GmbH 1988 ' DIM m$(22) !Menü erstellen RESTORE mmenue FOR z%=0 TO 21 READ m$(z%) NEXT z% mmenue: DATA DESK , Info ,-------------------- DATA 1,2,3,4,5,6,"" DATA GRAFIK , Flächen , Text ,---------------, Quit,"" DATA LAYOUT , Verschieben , Kopieren ,---------------,"","","" MENU m$() FULLW 1 !GEM-Fenster öffnen ' GOSUB menu PROCEDURE menu DEFMOUSE 0 DO ! Auf Ereignis ON MENU ! warten REPEAT ! und wenn UNTIL MOUSEK=0 ! Maustaste losgelassen ON MENU GOSUB auswahl ! verzweigen LOOP RETURN ' PROCEDURE auswahl !Auswahl treffen IF MENU(0)=1 MENU OFF GOSUB copyright ENDIF IF MENU(0)=11 MENU OFF GOSUB flaechen ENDIF IF MENU(0)=12 MENU OFF GOSUB text ENDIF IF MENU(0)=14 MENU OFF END ENDIF IF MENU(0)=17 MENU OFF GOSUB verschieben(0) ENDIF IF MENU(0)=18 MENU OFF GOSUB verschieben(1) ENDIF RETURN ' ' PROCEDURE verschieben(copy%) DEFMOUSE 5 ! Fadenkreuz DO ! Hauptschleife WHILE MOUSEK=0 ON MENU WEND ON MENU MOUSE xl%,yl%,k% ! Mauskoordinaten links-oben GRAPHMODE 3 DEFLINE 2,1,, ' ' ***** Rahmen zeichnen ***** ' WHILE MOUSEK=1 MOUSE xr%,yr%,k% ! Mauskoordinaten rechts-unten BOX xl%,yl%,xr%,yr% ! Verschiebe-Bild umrahmen REPEAT UNTIL MOUSEK=0 OR MOUSEX<>xr% OR MOUSEY<>yr% ! Wenn Maus bewegt BOX xl%,yl%,xr%,yr% ! alten Rahmen loeschen WEND DEFLINE 1,1,, GET xl%,yl%+38,xr%,yr%+38,snp$ ! Ausschnitt puffern IF NOT copy%=1 ! Nicht kopieren? DEFFILL 0 ! GRAPHMODE 1 ! PBOX xl%,yl%,xr%,yr% !dann Original überdecken DEFFILL 1 ENDIF DPOKE 9952,xl%+1 ! Mauscursor nach links-oben DPOKE 9954,yl%+38! zurücksetzen ' ' ***** Verschieben/Kopieren ***** ' WHILE MOUSEK=0 ON MENU MOUSE x%,y%,k% SGET bild$ ! Hintergrund puffern PUT x%,y%+38,snp$,7 ! Ausschnitt zeigen WHILE MOUSEX=x% AND MOUSEY=y% AND MOUSEK=0 ! Auf Mausbewegung warten ON MENU WEND SPUT bild$ !Hintergrund über Ausschnitt legen WEND PUT x%,y%+38,snp$,7 WHILE MOUSEK=1 !Warten bis Taste losgelassen WEND LOOP DEFTEXT ,0,,13 RETURN ' PROCEDURE flaechen GRAPHMODE 1 FOR z%=1 TO 3 STEP 2 DEFFILL ,2,RANDOM(24) PBOX 50*z%,50*z%,100*z%,100*z% NEXT z% DEFFILL 1 GOSUB menu RETURN ' PROCEDURE text GRAPHMODE 2 FOR z%=60 TO 300 STEP 80 TEXT 340,z%," Verschieben oder kopieren " NEXT z% GOSUB menu RETURN ' ' PROCEDURE copyright CLS BOX 120,70,530,270 DEFTEXT ,,,13 TEXT 150,130,"Verschieben und Kopieren von Bildausschnitten" DEFTEXT ,,,13 TEXT 260,170,"in GfA-Basic" DEFTEXT ,,,6 TEXT 230,210,"MAXON Computer 1988" DEFTEXT ,,,13 PAUSE 100 CLS GOSUB menu RETURN
Hans-H. Ackermann