Hardcopies von einzelnen Fenstern

Wer einmal auf dem Macintosh gearbeitet hat, kennt die praktische Möglichkeit, nur den Inhalt eines Fenster auf dem Drucker auszugeben. Damit auch die ATARI ST-Benutzer ihr Papier nicht mehr nur überwiegend mit dem Graumuster des Desktops füllen müssen, wurde das Accessory PRINTTOP geschrieben.

Mit ihm kann das jeweils aktive Fenster an den Drucker als Hardcopy geschickt werden. Dazu brauchen Sie nur den Eintrag “Print Window” im Deskmenü auszuwählen und zu bestätigen.

Das Programm baut dazu einen Bildschirm auf, der nur im Speicher vorhanden ist, aber nicht angezeigt wird. In ihn wird der Inhalt des obersten Fensters kopiert und dann die normale Hardcopy-Routine des Betriebssystems aufgerufen.

Aber zunächst müssen natürlich die Kennzahl sowie Größe und Lage des Fensters festgestellt werden. Das geschieht in den (nur zur Orientierung numerierten) Zeilen 66 bis 70. Graf_Handle liefert die Kennzahl der VDI-Arbeitsstation, auf der das AES zeichnet. Der erste WindowGet-Aufruf ergibt die Kennzahl des obersten Fensters, dessen Dimensionen im zweiten WindowGet-Call abgefragt werden.

Ausdruck eines Fensters mit dem PRINTTOP-Accessory

Falls ein Fenster vorhanden war, wird es zunächst zurechtgestutzt, wenn es teilweise außerhalb des Bildschirms lag. Um den privaten Bildschirm zu löschen, teilt das Programm dem Betriebssystem zunächst mit, daß er ab jetzt an einer anderen Speicheradresse liegt. Die VT52-Sequenz ESC E arbeitet dann wie gewünscht. Mit einem Rastercopy kann nun der Fensterinhalt in den Privatbildschirm kopiert werden. Das Ausdrucken geschieht dann einfach mit einem ScreenDump-Aufruf, der den logischen und nicht den sichtbaren Bildschirmspeicher ausgibt. Schließlich muß natürlich noch die Bildschirmadresse auf den ursprünglichen Wert gebracht werden.

Bei der Einrichtung des privaten Bildschirms im Speicher wird zunächst ein entsprechender Block von GEMDOS angefordert und dann die Adresse so aufgerundet, daß der Bildschirm an einer 512-Byte Grenze beginnt (Zeilen 41 bis 59). Das muß geschehen, da die Systemroutinen mit dem Bildschirm nur unter dieser Voraussetzung arbeiten können.

Der Rest des Programms besteht aus den üblichen Befehlen bei der Installation einen Accessories und Fehlerbehandlungen. Falls für den privaten Bildschirm nicht genügend Speicher frei war, sollten Sie andere Accessories entfernen oder die RAM-Disk verkleinern. Wenn Ihr System aber keine 32 KByte nach dem Booten mehr frei hat, können Sie sowieso kaum etwas starten, so daß dieser Fall praktisch nie auftreten wird.

Da die Standard-Hardcopy benutzt wird, ist keine Druckeranpassung notwendig. Wenn Sie z.B. einen 24-Nadel-Drucker oder einen anderen nicht EPSON-kompatiblen besitzen, kann PRINTTOP dann arbeiten, wenn ein spezieller Hardcopytreiber installiert ist. Für die P6/P2200-Drucker von NEC ist ein solches Programm als public-domain verfügbar, wie auch für andere.

Wenn es Sie stört, daß der Fensterrahmen mitausgedruckt wird, brauchen Sie nur in Zeile 70 “CurrXYWH” und "WorkXYWH” auszutauschen. Das AES liefert dann die Dimensionen der inneren Fensterfläche beim Window-Get-Aufruf.

Im Bild sehen Sie eine Fensterhardcopy, die mit PRINTTOP erstellt wurde. Dabei mußten keine störenden grauen Flächen vom Desktop-Hintergrund mehr entfernt werden.

MOOULE PrintTopWindow;

(* Robert Tolksdorf 5.2.88 *)

(*$A+*) (* Optimieren *)

FROM SYSTEM IMPORT ADR, ADDRESS;
FROM GEMAESbase IMPORT AccessoryOpen, Top, CurrXYWM, MouseOff, MouseOn, AESCallResult ; 
FROM AESApplications IMPORT ApplInitialise;
FROM AESForms IMPORT FormAlert; 
FROM AESGraphics IMPORT GrafHandle, GrafMouse;
FROM AESMenus IMPORT MenuRegister; 
FROM AESEvents IMPORT EventMessage;
FROM AESWindows IMPORT WindowGet;
FROM GEMVDIbase IMPORT BigPxyArrayType;
FROM VDIRasters IMPORT MFDBType, CopyRasterOpaque ; 
FROM GEMDOS IMPORT Alloc, ConOut; 
FROM XBIOS	IMPORT	ScreenLogicalBase, SetScreenBase, 5creenDump;

CONST Title	=	'   Print Window';
		NoMemAlert = '[13 [Nicht genug| Speicher frei] [OK]';
		RebootAlert = 'Sorgen Sie für mehr Speicher|und booten Sie neu][OK]'; 
		ReallyAlert = '[3][Fensterlausdrucken ?] [OK|CANCEL] ';
		NoWindAlert = '[1][Kein Fenster|vorhanden !][OK]';
VAR
	Msg	:	ARRAY [0..16] OF INTEGER;
	SHandle, tophandle,
	applID, menuID,
	x, y, w, h	:	INTEGER;
	mymemory	:	ADDRESS;
	ScreenMFDB, MyMFDB :	MFDBType;
	pxyarray	:	BigPxyArrayType;

BEGIN

(* Application initialisieren u. Accessory anmelden *) 
	applID := ApplInitialise(); 
	menuID := MenuRegister(applID,Title);
	(* Speicher für Privatbildschirm anfordern *)
	Alloc(32511,mymemory);
	IF mymemory<»0 TUEN
		(* Kein Speicher frei ... *) 
		x:=FormAlert(1,NoMemAlert)+FormAlert(1,RebootAlert);
		LOOP EventMessage(ADR(Msg)) END 
	ELSE
		(* MFDB's setzen *)
		WITH ScreenMFDB DO
			pointer:=ScreenLogicalBase(); 
			width:=639; (* mono-Bildschirm !! *) 
			height:=399; 
			widthU:=40; 
			format:=1; 
			planes:=1 
		END;
		MyMFDB:=ScreenMFDB;
		(* Privatbildschirm an 1/2 KByte-Grenze setzen *) 
		MyMFDB.polnter:=
			ADDRESS(LONGCARD(mymemory)*512-(LONGCARD(mymemory) MOD 512));
		LOOP
			(* Auf Mitteilung warten *)
			EventMessage(ADR(Msg));
			(* Fenster ausdrucken ??? *)
			IF (Msg[0]=AccessoryOpen) AND (FormAlert(1, ReallyAlert)=1) THEN 
				(* AES MOI-Handle holen *)
				SHandle:=GrafHandle(x,x,x,x);
				(* Handle des obersten Fensters in tophandle holen *)
				WindowGet(SHandle,Top,tophandle,x,x,x);
				(* Größe des obersten Fensters holen *)
				WindowGet(tophand1e,CurrXYWH,x,y,w,h);
				IF AESCallResult>0 THEN (* Clippen *)
					IF x+w>INTEGER(ScreenMFDB.width) THEN 
						w:=INTEGER(ScreenMFDB.width)-x+1;
					END;
					IF y+h>INTEGER(ScreenMFDB.height) THEN 
						h:=INTEGER(ScreenMFDB.height)-y+1;
					END;
					(* Maus ausschalten *)
					GrafMouse(MouseOff,NIL);
					(* logisch auf Privatbildschirm umschalten *) 
					SetScreenBase(MyMFDB.pointer,NIL,-1);
					(* Privatbildschirm löschen *)
					ConOut(CHR(27)); ConOut('E');
					(* Fenster in Privatbildschirm kopieren *) 
					pxyarray[0]:=x;		pxyarray[1]:=y;
					pxyarray[2]:=x+w-1; pxyarray[3]:=y+h-1;
					pxyarray[4]:=0; pxyarray[5]:=0;
					pxyarray[6]:=w-1; pxyarray[7];=h-1;
					CopyRasterOpaque(SHandle,3,pxyarray, ADR(ScreenMFDB),ADR(MyMFDB));
					(* Dumpen *)
					ScreenDump;
					(* logisch wieder auf eigentlichen Bildschirm umschalten *)
					SetScreenBase(ScreenMFDB.pointer,NIL,-1);
					(* Maus einschalten *)
					GrafMouse(MouseOn,NIL);
				ELSE
					x:=FormAlert(1,NoWindAlert)
				END;
			END
		END
	END
END PrintTopWindow.

Robert Tolksdorf
Aus: ST-Computer 05 / 1988, Seite 122

Links

Copyright-Bestimmungen: siehe Über diese Seite