16.6 Drucken von Grafiken
16.6.1 Das Problem der Maßeinheiten
Widmen wir uns nun der Beziehung zwischen den Maßeinheiten der Bildschirmausgabe und der Druckerausgabe. Dazu verwenden wir ein einfaches Programm, das auf dem Monitor ein Quadrat von 100 × 100 Einheiten ausgibt und es durch Klick auf eine Schaltfläche ausdruckt.
Private Sub Skalierung_Paint(sender As Object, e As PaintEventArgs) _ Handles MyBase.Paint Dim g As Graphics = e.Graphics g.DrawRectangle(New Pen(Brushes.Black, 1), 10, 10, 100, 100) End Sub Private WithEvents doc As New PrintDocument() Private Sub Druck(sender As Object, e As PrintPageEventArgs) _ Handles doc.PrintPage Dim g As Graphics = e.Graphics g.DrawRectangle(New Pen(Brushes.Black, 1), _ g.VisibleClipBounds.X, g.VisibleClipBounds.Y, 100, 100) End Sub
Sie werden feststellen, dass die beiden Quadrate unterschiedlich groß sind. Messen Sie die Kantenlänge des ausgedruckten Quadrats nach – es sind 25,4 mm. Wie groß die Kantenlänge auf dem Bildschirm ist, hängt von dessen Auflösung ab.
Die unterschiedlichen Abmessungen der beiden Quadrate lassen sich auf verschiedene Einheiten zurückführen, die den beiden Graphics-Objekten zugrunde liegen. Die Koordinatenwerte, die an die Zeichenfunktionen des Graphics-Objekts des PrintPage-Ereignisses übergeben werden, werden standardmäßig in Einheiten von 1/100 Zoll gemessen. Das entspricht der Einstellung der Eigenschaft PageUnit=GraphicsUnit.Display. Die 100 Einheiten, die wir im Beispiel oben zur Festlegung der Kantenlänge angegeben haben, führen deshalb zu einer Ausgabe, die exakt ein Zoll ist. War die Ausgabe der Grafik basierend auf diesem Maßsystem beabsichtigt, brauchen wir uns keine weiteren Gedanken zu machen. Stand hinter der Kantenlänge von 100 Einheiten jedoch die Absicht, ein Quadrat von 100 mm zu zeichnen, müssen wir die Druckausgabe noch an das metrische System anpassen.
Die Einheit der Bildschirmausgabe ist standardmäßig Pixel. Die PageUnit-Eigenschaft des Graphics-Objekts des Paint-Ereignisses hat demnach den Wert GraphicsUnit.Pixel. Damit ergibt sich als Seitenlänge des Quadrats 100 Pixel * Pixelgröße. Letztere wird durch die Bildschirmabmessungen und die gewählte Auflösung bestimmt. Das Graphics-Objekt hat die schreibgeschützten Eigenschaften DpiX und DpiY. Sie können diese Einstellungen unter Windows ändern, wie in den folgenden drei Screenshots zu sehen ist. Ist das Lineal richtig eingestellt, werden fortan Grafiken in der richtigen Größe ausgegeben. Leider ist auf meinem System die Schriftdarstellung dann etwas »ungewohnt«. Im Internet wird von weiteren Fontproblemen berichtet, also: Die Änderung erfolgt auf eigenes Risiko.
Abbildung 16.7 Bildschirmeinstellungen und DPI
Abbildung 16.8 Bildschirmskalierung
16.6.2 Festlegung der Einheiten und Skalierung
In Abschnitt 16.2.5, »Das Das Ereignis PrintPage«, haben wir uns bereits die Eigenschaft PageUnit des Graphics-Objekts und ihre Auswirkungen auf die Darstellung geometrischer Figuren angesehen. Wir können diese Eigenschaft so einstellen, dass das geometrische Objekt in der richtigen Größe auf dem Papier landet. Soll unser Quadrat eine Kantenlänge von 100 mm haben, ergänzen wir im PrintPage-Ereignis die folgende Anweisung:
e.Graphics.PageUnit = GraphicsUnit.Millimeter
Die Maßangaben werden jetzt nicht mehr in 1/100 Zoll gemessen, sondern in Einheiten von einem Millimeter. Die Folge ist, dass das Quadrat mit einer Kantenlänge von 100 mm ausgedruckt wird, während die Grafikausgabe auf dem Bildschirm unverändert bleibt – zumindest solange wir im Paint-Ereignis keine Änderung der Einheiten vornehmen.
Es kommt vor, dass wir deutlich größere Figuren ausdrucken lassen wollen, zum Beispiel das quadratische Grundstück einer Villa – 100 × 100 m2 oder 100000 × 100000 mm2. Sie sind also gezwungen, die Maße so zu skalieren, dass sie noch auf das Druckpapier passen. Dazu können Sie einen unbequemen Weg wählen und die Maße bereits vor der Eingabe skalieren, oder Sie nutzen die Eigenschaft PageScale im Graphics-Objekt. Mit
e.Graphics.PageUnit = GraphicsUnit.Millimeter e.Graphics.PageScale = 0.001
erhalten Sie wieder ein Quadrat, das mit einer Kantenlänge von exakt 100 mm ausgedruckt wird – sofern Sie das Graphics-Objekt im PrintPage-Ereignis so festlegen.
16.6.3 Größenrichtige Ausgabe einer Grafik
Im folgenden Beispiel wird ein Quadrat in Pixeleinheiten angezeigt und mit einer Seitenlänge von 50 mm auf dem Drucker ausgedruckt. Innerhalb des Quadrats beschreibt darüber hinaus eine Zeichenfolge die Größe des geometrischen Objekts.
'...\Drucken\Druck\Skaliert.vb |
Imports System.Drawing.Printing Public Class Skaliert Private Sub Draw(g As Graphics, x As Integer, y As Integer) Dim c As Color = Color.Black Dim f As Font = New Font("Arial", 8) g.DrawRectangle(New Pen(c), x, y, 50, 50) g.DrawString("Größe: 50x50", f, New SolidBrush(c), New Point(x + 2, y + 2)) End Sub Private Sub Bildschirm(sender As Object, e As PaintEventArgs) _ Handles MyBase.Paint Dim g As Graphics = e.Graphics g.PageUnit = GraphicsUnit.Millimeter g.PageScale = 1.15 ' bildschirmabhängig, nach DPI-Anpassung 1.0 Me.Draw(g, 0, 0) End Sub Private WithEvents doc As New PrintDocument() Private Sub Drucker(sender As Object, e As PrintPageEventArgs) _ Handles doc.PrintPage Dim g As Graphics = e.Graphics g.PageUnit = GraphicsUnit.Millimeter Me.Draw(g, e.MarginBounds.X * 25.4\100, e.MarginBounds.Y * 25.4\100) End Sub Private Sub Druck(sender As Object, e As EventArgs) Handles Drucken.Click doc.Print() End Sub End Class
Da die beiden Methoden DrawString und DrawRectangle sowohl zur Anzeige auf dem Bildschirm als auch zur Ausgabe des Druckers aufgerufen werden, sollten sie in einer eigenen Methode stehen, die von den beiden Ereignishandlern aufgerufen wird. Der Routine Draw werden nur der Grafikkontext und die Position des Rechtecks übergeben. Alle Größenangaben sind innerhalb von Draw fixiert, um für Bildschirm und Drucker identische Zahlenwerte zu verwenden.
Die Kantenlänge des Quadrats beträgt 50 Einheiten. Damit dies 50 mm entspricht, werden die Einheiten beider Grafikkontexte auf Millimeter festgelegt.
g.PageUnit = GraphicsUnit.Millimeter
Wenn die Bildschirmauflösung in DPI (dots per inch) nicht der realen Bildschirmauflösung entspricht, sollte die Eigenschaft PageScale im Ereignishandler von Paint entsprechend gesetzt werden, um die Umrechnung jeder einzelnen Koordinate zu vermeiden. Auf meinem System ist ein Faktor von 1.15 gerade passend.
g.PageScale = 1.15
Im zweiten und dritten Parameter erwartet Draw die Koordinaten x und y für den Startpunkt des auszudruckenden Quadrats. Die Linienmitten der linken und oberen Kante des Quadrats sollen gerade mit dem in MarginBounds definierten Rand zusammenfallen. MarginBounds liefert aber nur »Einheiten«, nämlich genau 100. Als 1/100 Zoll interpretiert, bedeutet das einen Seitenrand von 25,4 mm (plus des obligatorischen außerhalb des Druckbereichs liegenden Rands). Da wir aber auf GraphicsUnit.Millimeter umgeschaltet haben, werden diese Angaben in Millimeter gemessen und würden zu einem Randabstand des Quadrats von über 10 cm führen. Damit die Einheiten richtig interpretiert werden, müssen wir den Wert von MarginBounds mit 0,254 multiplizieren (die ganzzahlige Division »\« vermeidet eine Typumwandlung in Integer):
e.MarginBounds.X * 25.4\100
Linienbreite des Zeichenstifts
Hinsichtlich der Linienbreite der Druckausgabe können wir uns ein Problem einhandeln. Im Beispiel Skaliert legt das Pen-Objekt für den Aufruf der DrawRectangle-Methode nur die Farbe fest:
New Pen(c)
Da wir keine Stiftbreite angegeben haben, beträgt diese standardmäßig 1. Ohne Festlegung der Einheit ist das 1 Pixel in der Bildschirmausgabe und 1/100 Zoll in der Druckausgabe. Wir haben GraphicsUnit.Millimeter eingestellt, also sind die Linien 1 mm breit. Wünschen wir eine andere Linienbreite, müssen wir das schon beim Konstruktoraufruf berücksichtigen. Beispielsweise wird die folgende Anweisung im Programmbeispiel zu einer Strichbreite von 0,5 mm führen:
New Pen(c, 0.5)
Schriftgröße der Druckausgabe
Die Größe einer Schrift wird nicht durch die Eigenschaften PageScale und PageUnit beeinflusst. Ausschlaggebend ist nur die Schriftgröße, die in Punkteinheiten angegeben ist. Von den vielen existierenden Punktmaßen wird in der Softwaretechnologie (fast) ausschließlich ein Punkt der Größe 1/72 Zoll verwendet, was etwa 0,0139 Zoll entspricht. Im Beispielprogramm wird die Größe der Schrift mit 8 Punkt festgelegt, also ca. 0,11 Zoll bzw. 2,8 mm.
Wenn Ihnen die Umrechnung zu aufwändig ist, können Sie auch andere Konstruktoren der Font-Klasse benutzen, die neben der Angabe der Schriftfamilie (bzw. der Schriftart als Zeichenfolge) und der Schriftgröße auch eine Einheit vom Typ GraphicUnit spezifizieren. Mit
Dim f As New Font("Arial", 8, GraphicsUnit.Millimeter)
wird die Höhe einer auf diesem Font basierenden Zeichenfolge 8 mm betragen. Sie können auch zur Bildschirmausgabe eine von Punkt abweichende Maßeinheit angeben. Sie sollten dabei jedoch berücksichtigen, dass die tatsächliche Höhe auf dem Monitor auch von der DPI-Einstellung unter Windows abhängt.
Hinweis |
Der Schriftgrad ist minimal größer als die tatsächliche Buchstabengröße. |
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.