AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Delphi Drucken
Tutorial durchsuchen
Ansicht
Themen-Optionen

Drucken

Ein Tutorial von Dipl Phys Ernst Winter · begonnen am 21. Mai 2009 · letzter Beitrag vom 24. Nov 2019
Antwort Antwort
Seite 2 von 3     12 3      
Dipl Phys Ernst Winter
Registriert seit: 14. Apr 2009
Drucken aus Delphi
Aus Delphi zu drucken ist so einfach, dass es schwierig zu verstehen ist. (Um das zu belegen, braucht man sich nur in der einschlägigen Literatur umzusehen.)
Das Objekt Printer
Nachdem die Unit Printers in die uses-Klausel der Formular-Unit einer Anwendung aufgenommen ist, steht dieser eine Objekt Printer der Klasse TPrinter zur Verfügung, ohne dass eine Variablen Printer deklariert und ihre Instanz erzeugt werden muss.
Hier beginnen mit der Assoziation 'Drucker' zu dem unglücklich gewählten Namen 'Printer' ('PrintJob' hätte falsche Assoziationen vermieden) die Schwierigkeiten. Die Instanzen von TPrinter sind jedoch keine Drucker (beziehen sich auch nicht auf einen Drucker), sondern sind als Objekte anzusehen, die Druckjobs (Druckaufträge) bearbeiten. Ohne eine erste Instanz von TPrinter wäre die Unit Printers sinnlos, daher wird diese gleich beim Einbinden der Unit erzeugt. Mit dem gesetzten Namen 'Printer' wird der Code vereinheitlicht.
Die Druckaufträge (Jobs) des Objekts Printer werden mit seinen Methoden bearbeitet. Dazu sind folgende Schritte notwendig:
• Auswahl des Druckers
Printer.Printers gibt eine Liste der verfügbaren Drucker zurück, aus der mit Printer.PrinterIndex ein Drucker ausgewählt werden kann. Printer.PrinterIndex:= -1 wählt den Standarddrucker.
• Setzen der Druckereigenschaften: Papierformat, Ausrichtung Hoch-/Quer, Anzahl der Kopien....
Printer.Orientation:= poPortrait setzt Hochformat, Printer.Orientation:= poLandscape setzt Querformat.
• Starten des Druckauftrages mit BeginDoc: Stellt eine leere Printer.Canvas für die erste Seite zur Verfügung.
• Beschreiben der Printer.Canvas unter Beachtung der Druckerauflösung.
• Optional kann mit NewPage zur nächsten Seite gewechselt werden. Über die fertige Canvas der letzen Seite wird auf einen Stack eine neue angelegt, die anschließend beschrieben werden kann.
• Beenden des Druckauftrages mit EndDoc: Schickt den Stapel der Printer.Canvas an den Druckerspoiler. Windows übernimmt das Ausdrucken.
Zwischen den Jobs kann der Drucker und die Ausrichtung auf Hoch- bzw. Querformat gewechselt werden.
Fehlermeldung 'Der Drucker ist am Drucken', wenn zwischen BeginDoc und EndDoc versucht wird PrinterIndex oder Orientation zu ändern.
Fehlermeldung 'Der Drucker ist nicht am Drucken', wenn außerhalb von BeginDoc und EndDoc versucht wird auf die Printer.Canvas zu schreiben.
Anmerkung: Indem man 'NewPage;'durch 'EndDoc; BeginDoc;'ersetzt, kann man einen mehrseitigen Druckauftrag in einzelne Druckaufträge für seine Seiten aufteilen. Die Seiten werden dann in natürlicher Folge an den Druckspoiler gegeben.
Die Druckerauflösung
Die Auflösung eines Druckers übersteigt im allgemeinen die Auflösung eines Bildschirmes. Sie ist von Drucker zu Drucker verschieden und kann für den gleichen Drucker (abhängig vom Druckertreiber) verschieden sein.
Verwenden Sie keine standardisierte Auflösung für Ihren Drucker, das kann bei einem Wechsel des Druckers oder Druckertreibers die unangenehme Folge haben, dass Sie alle Ihre Routinen zum Drucken überarbeiten müssen!
Man kann die Druckerauflösung auf Millimeter des Papierformates und auf Pixel des Bildschirms beziehen.
Der Bezug auf Millimeter des Papiers ist für Größen bequem, die keine Entsprechung auf dem Bildschirm haben: z. B. linker und oberer Rand: Den Maßstab m (Pixel/mm) ermittelt man (für DIN A4 im Hochformat) nach Wahl des Druckers mit
m:= Printer.PageHeight/297       // Druckerauflösung Pixel/mm oder
m:= Printer.PageWidth/205; // Druckerauflösung Pixel/mm und setzt z.B. die Position für einen linken Rand von 20mm mit
LRand:= Round(m*20); Bezug auf Pixel des Bildschirms ist notwendig für Größen, die in Bildschirmpixeln gegeben sind, wie z.B. die Breite von Spalten eines StringGrid. Den Maßstab ms (Druckerpixel/Bildschirmpixel) ermittelt man nach Wahl des Druckers und kann anschließend z.B. Tabulatoren für die Ausgabe der Zeilen eines StringGrid setzen:
Delphi-Quellcode:
ms:= Printer.PageWidth/Screen.Width; R[0]:= Round(m*lr); // Tabulatoren setzen
for i:= 0 to StrGrid.ColCount-1 do
  R[i+1]:= R[i] + Round(ms*StrGrid.ColWidths[i]);
mit denen man eine Zeile des StringGrid drucken kann
Delphi-Quellcode:
for k:= 0 to StrGrid.ColCount-1 do
  TextOut(R[k], h, StrGrid.Cells[k, i]);
Mehrere Druckjobs
Um mehrere Druckjobs gleichzeitig zu bearbeiten, sind weitere Instanzen von TPrinter notwendig,. Sie werden wie üblich nach Deklaration einer Variablen Printer2: TPrinter; mit dem Construktor von TPrinter angelegt:
Printer2:= TPrinter.Create;
Mit Printer.BeginDoc; und Printer2.BeginDoc werden zwei verschiedene Canvas erzeugt, die in beliebiger Folge beschrieben werden können und jederzeit mit Printer.EndDoc bzw. Printer2.EndDoc an den entsprechenden Druckerspoiler geschickt werden können. Den Druckjobs können verschiedene aber auch der gleiche Drucker zugeordnet sein.
Zwei Druckjobs sind Beispielhaft, wenn in beliebiger Folge Koeffizienten einer Approximations-Funktion (einspaltig) und Wertetabellen (mehrsoaltig) gedruckt werden sollen.
Hinweis: Beim Schließen einer Anwendung gibt Delphi eine von Printer nicht geschlossene Druckseite aus, für weitere Instanzen von TPrinter muss das die Anwendung selbst übernehmen, wenn keine Druckseiten verloren gehen sollen.

Für die Verwendung von mehreren Druckjobs habe ich ein Demo gepostet.
Angehängte Dateien
Dateityp: zip zweidruckjobs_247.zip (133,5 KB, 108x aufgerufen)
Autor: DP Ernst Winter
 
Klaus01

 
Delphi 10.4 Sydney
 
#11
  Alt 21. Mai 2009, 19:13
Zitat von Luckie:
Warum setzt ihr den Mapmode nicht auf LOMETRIC? Dann habt ihr 10/Millimeter.
Guten Abend,

sollte es nicht Millimeter/10 heißen, also 0,1 Millimeter?

Grüße
Klaus

P.S. Wie war der erste Vatertag?
Klaus
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

 
Delphi 2006 Professional
 
#12
  Alt 21. Mai 2009, 19:35
Äh, ja.Zu viel sauerstoff. Ich war heute den ganzen Nachmittag im Tierpark Sababurg unterwegs mit Anne und meiner Freundin..
Michael
  Mit Zitat antworten Zitat
Whatever
 
#13
  Alt 8. Jul 2009, 12:34
Hallo,

kann mir zufällig jemand sagen, was "Mapmode" ist und was auf "Lometric" gesetzt werden muss.

Tierpark Sababurg? ganz bei mir in der Nähe

Grüße Whatever
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

 
Delphi 11 Alexandria
 
#14
  Alt 8. Jul 2009, 12:53
MSDN-Library durchsuchenSetMapMode, da ist das beschrieben
Detlef
  Mit Zitat antworten Zitat
Whatever
 
#15
  Alt 8. Jul 2009, 13:03
Ah vielen Dank!
Also sind, wenn ich den Mapmode des Druckers auf Lometric stelle, alle Angaben in 0.1 Millimeter richtig?
Grüße Whatever
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

 
Delphi 11 Alexandria
 
#16
  Alt 8. Jul 2009, 18:11
Richtig. Was noch wichtig ist:
Zitat:
Positive x is to the right; positive y is up.
, d.h. die Y-Koordinaten werden anders behandelt, als man das normalerweise gewohnt ist.
Detlef
  Mit Zitat antworten Zitat
alzaimar

 
Delphi 2007 Enterprise
 
#17
  Alt 8. Jul 2009, 18:52
Seit mir nicht böse, aber wieso verwendet ihr keinen Reportgenerator? Zum programmieren nehmt ihr doch auch die Delphi-IDE und kein Notepad.EXE?
  Mit Zitat antworten Zitat
Whatever
 
#18
  Alt 8. Jul 2009, 21:00
Also alle Y-Werte *(-1).
Gut dankeschön für die Hilfe.
Alzaimar mit deinem Post kann ich ehrlich gesagt nichts anfangen...
  Mit Zitat antworten Zitat
RaSoWa1

 
Delphi 2010 Professional
 
#19
  Alt 8. Jul 2009, 21:09
Zitat:
m:= Printer.PageHeight/297 // Druckerauflösung Pixel/mm
liefert ggf. einen falschen Wert, da der nicht druckbare Bereich nicht berücksichtigt wird. Viele Drucker haben links, rechts, oben und unten einen nicht druckbarenn Bereich von ca. 2 bis 5 mm.
Besser ist deshalb, gerade weil es eine API ist:
Zitat:
GetDeviceCaps(Printer.Handle, LOGPIXELSX) / 2.54

Zitat:
getDeviceCaps(Printer.Handle,HORZSIZE); // (Bedruckbare Breite in mm)
getDeviceCaps(Printer.Handle,VERTSIZE); // (Bedruckbare Höhe in mm)
Gibt es auch eine Funktion die mir die Größe der nicht druckbaren Ränder liefert?

Gruß Klaus
Klaus
  Mit Zitat antworten Zitat
samso
 
#20
  Alt 10. Jul 2009, 13:04
Das muß aus diversen Parameter zurückgerechnet werden. Der linke und der obere Rand ergibt sich aus PHYSICALOFFSETX, PHYSICALOFFSETY. Der rechte und der untere Rand muß dann aus PHYSICALWIDTH, PHYSICALHEIGHT abzüglich HORZRES unter Berücksichtigung von LOGPIXELSX bzw. VERTRES unter Berücksichtigung von LOGPIXELSY berechnet werden.
Delphi-Quellcode:
function GetDefaultMinMargins: TRect;
var
  XResolution, YResolution: Extended;
  PhysicalPage: TPoint;
  PrintablePage: TPoint;
  Offset: TPoint;
begin
  XResolution := 1/GetDeviceCaps(Printer.Handle, LOGPIXELSX)*1000;
  YResolution := 1/GetDeviceCaps(Printer.Handle, LOGPIXELSY)*1000;
  PhysicalPage.X := GetDeviceCaps(Printer.Handle, PHYSICALWIDTH);
  PhysicalPage.Y := GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT);
  PrintablePage.X := GetDeviceCaps(Printer.Handle, HORZRES);
  PrintablePage.Y := GetDeviceCaps(Printer.Handle, VERTRES);
  Offset.X := GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);
  Offset.Y := GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY);
  Result.Left := trunc(Offset.X*XResolution+0.5);
  Result.Top := trunc(Offset.Y*YResolution+0.5);
  Result.Right := trunc((PhysicalPage.X-Offset.X-PrintablePage.X)*XResolution+0.5);
  Result.Bottom := trunc((PhysicalPage.Y-Offset.Y-PrintablePage.Y)*YResolution+0.5);
end;
Wenn ich mich richtig erinnere war das Ergebnis dann in 1/1000 inches
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:52 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz