| |
VB.NET - FortgeschritteneSchrifthöhe mit Graphics-Funktion "MeasureString" für Display und Druck | | | Autor: Rainer | Datum: 19.12.17 17:01 |
| Hallo,
ich habe eine Routine geschrieben, mit der Datensätze einer DB-Tabelle gedruckt werden. Vor der Druckausgabe erzeuge ich eine Bildschirmübersicht mit dem Steuerelement "PrintPreviewControl". Diese dient in erster Linie dazu die Seitenanzahl der Dokuments zu ermitteln und damit eine Auswahl der zu druckenden Seiten zu ermöglichen. In der Testphase habe ich mit einer DB-Tabelle, die anhand der von PrintPreviewControl erstellten Übersicht insgesamt 99 Druckseiten ergab, gearbeitet. Als ich versuchte die Seite 99 auszudrucken, erhielt ich eine leere Seite. Erst bei Seite 97 erhielt ich das Ende der Liste gedruckt. Ein Vergleich mit dem Inhalt der DB-Tabelle stellte ich fest: es fehlte kein einziger Datensatz.
Daraufhin prüfte ich die Seite 1 genauer und fand heraus, daß diese im Vergleich zur Bildschirmanzeige zwei Datensätze mehr enthielt.
Zur Herangehensweise beim Aufbau der zu druckenden Datenzeile: mit der Graphics-Funktion "MeasureString" ermittle ich die für die Druckausgabe erforderliche Druckraumhöhe (abhängig von der FONT-Einstellung), prüfe ob dieser Platz auf der Seite noch verfügbar ist und führe den Druck ggf. auf der neuen Seite aus.
Bei der Suche nach der Ursache für die unterschiedliche Datensatzanzahl pro Seite stellte ich fest, daß die Graphics-Funktion für die Zeilenhöhe bei gleicher FONT-Einstellung (Schriftart, Style und Size) für die Darstellung im PrintPreviewControl und in der Druckausführung unterschiedliche Werte berechnet.
Beispiel:
Zeilenhöhe bei Arial, 11, mager für Display 19,478 Grafikpunkte und für den Druck 18,978 Grafikpunkte; das sind beim Druck im Vergleich zur Bildschirmdarstellung 2,566 % weniger Grafikpunkte. Dieser Prozentsatz ist stabil, d.h. er gilt für alle von mir getesteten FONT-Einstellungen. Ich konnte dies aber nur an einem Drucker (Brother MFC-J480 DW) testen. Da es sich bei MeasureString um eine Systemfunktion handelt, würde ich eine druckerabhängige Ursache ausschließen.
Bevor ich nun in meinem Algorithmus einen Korrekturfaktor einführe, möchte ich Euch fragen:
1. Hat jemand von Euch auch diese Diskrepanz festgestellt?
2. Welche anderen Möglichkeiten der Umgehung dieser Diskrepanz kennt Ihr?
3. Habe ich ggf. die Graphics-Funktion falsch verwendet?
In der Hoffnung jemand kann mir weiterhelfen, wünsche ich der Forum-Gemeinde schöne Feiertage.
Rainer. | |
Re: Schrifthöhe mit Graphics-Funktion "MeasureString" für Display und Druck | | | Autor: sv00010 | Datum: 20.12.17 19:40 |
| Es gibt noch zu überprüfen, ob die Seitenränder bei der Anzeige und beim Druck eventuell verschieden sind.
Du solltest eventuell von beiden Screenshots machen und dann im Grapfikprogramm auf die höchste Vergrößerung stellen und bei einer gleichen Zeile bei beiden mal die Pixelanzahl zählen und vergleichen. | |
Re: Schrifthöhe mit Graphics-Funktion "MeasureString" für Display und Druck | | | Autor: Kuno60 | Datum: 21.12.17 00:36 |
| Hallo,
dieses Problem ist mir seit Jahren bekannt und ich wäre auch an einer Lösung interessiert.
MeasureString liefert bei gleichem Font, 3 verschiedene Größen:
- beim zeichnen auf dem Bildschirm
- beim zeichnen im PrintPreviewControl
- beim ausdrucken
Dieses Verhalten ist unabhängig vom Font und vom Drucker.
Es werden nicht nur unterschiedliche Größen gemessen, sondern auch unterschiedliche Größen gezeichnet.
Folgendes habe ich festgestellt:
Bei der Ausgabe an den Drucker wird 100 DPI verwendet und bei der Ausgabe auf den Bildschirm 96 DPI.
Das PrintPreviewControl scheint irgendwie Zoll in Millimeter umzurechnen. Der Wert von 2,566% deutet darauf hin und es werden alle Strings 2,566% größer gezeichnet.
Dies betrifft nur DrawString. Die anderen Funktionen wie DrawRectangle usw. sind davon nicht betroffen.
"PrintableArea" liefert die exakte Größe des druckbaren Bereiches. Damit kann man die genaue Zeilenanzahl berechnen und es wird korrekt gedruckt. Die Darstellung im PrintPreviewControl kann dann aber abweichen. | |
Re: Schrifthöhe mit Graphics-Funktion "MeasureString" für Display und Druck | | | Autor: Manfred X | Datum: 21.12.17 09:08 |
| Hallo!
Das Problem hängt vermutlich an den Unterschieden zwischen
Dot und Pixel.
Ich setze gewöhnlich bei der Aufbereitung des Ausdrucks
harte Seitenumbrüche, um sicherzustellen, daß bestimmte
inhaltliche "Blöcke" jeweils auf einer Seite gedruckt werden.
Das Windows.Forms zugrundeliegende Graphik-System ist veraltet.
Beitrag wurde zuletzt am 21.12.17 um 09:12:10 editiert. | |
Re: Schrifthöhe mit Graphics-Funktion "MeasureString" für Display und Druck | | | Autor: Franki | Datum: 23.12.17 04:20 |
| Hallo Manfred X
Zitat: | |
Ich setze gewöhnlich bei der Aufbereitung des Ausdrucks
harte Seitenumbrüche, um sicherzustellen, daß bestimmte
inhaltliche Blöcke jeweils auf einer Seite
gedruckt werden. | |
Und wie ermittelst du die jeweiligen Blöcke bzw. deren Größe? Du gehst das ja bestimmt nich per Hand in der Vorschau durch und verschiebst dann Teile auf eine andere Seite. Und was ist wenn ein Block mal mehrere Seiten lang ist?
Bei den MS Office Programmen hat man ja vorher diverse Einstellmöglichkeiten, die sollte man für die eigene Anwendung auch so gestalten. Ist wie man an der Frage sieht oft schwierig, aber je nach Anwendung kann das passen wie du es beschreibst.
Zitat: | |
Das Windows.Forms zugrundeliegende Graphik-System ist
veraltet. | |
Hast du eine Alternative?
Gruß und frohe Weihnachten,
Frank | |
Re: Schrifthöhe mit Graphics-Funktion "MeasureString" für Display und Druck | | | Autor: Manfred X | Datum: 23.12.17 11:09 |
| Hallo!
Die Größe des druckbaren Bereichs für die gültige Printereinstellung
kann abgefragt werden - die Zahl der Zeilen pro Seite bzw. die Blockhöhe
läßt sich (wie von Kuno60 dargelegt) "ungefähr" ermitteln und der Platzbedarf
wird bei der Seitenaufteilung per Code ggf. automatisch abgerundet.
(Die Seitenanzeige der Druckvorschau ist dafür keine geeignete
Bezugsgröße.)
Da ich - als "Umweltfanatiker" (kein Auto, kaum Fleisch, nur Stromspar-
Computer) - nur selten etwas drucke, habe ich mir über Alternativen zu
den integrierten Net-Druckfunktionen noch keine Gedanken gemacht.
Direkt ausgedruckt wird von mir ohnehin kaum etwas, sondern es werden
gewöhnlich Druckdateien erzeugt. (Die kann man als Druck-Vorschau
verwenden). | |
Re: Schrifthöhe mit Graphics-Funktion "MeasureString" für Display und Druck | | | Autor: Rainer | Datum: 25.12.17 13:02 |
| Hallo,
auch Euch allen ein schönes Weihnachtsfest.
Ich habe einige Zeit gebraucht, aber jetzt habe ich eine - zumindest für meine Bedürfnisse eine brauchbare - Lösung, die ich Euch aus Platzgründen (> 5 kB) in den nachfolgenden zwei Antworten präsentiere. Mit dem Bemerkungsteil sind diese zwei Antworten ebenfalls zu groß, sodaß ich die Bemerkungen für beide Funktionen hier anzeige:
''' <remarks>Die Parameter TEXT, SCHRIFT und BREITE entsprechen den
' MEAURESTRING-Parametern text, font und width.
''' Auf die Verwendung der restlichen Parameter der Graphics-Funktion wurde
' verzichtet, da diese in der Applikation
''' keine Verwendung finden.
''' Bei Übergabe eines Leerstring ist das Ergebnis SIZEF(0;0).
''' Der Schalter ISPRINTEROUT wird in der Ereignisroutine BEGINPRINT mit
' der Anweisung
''' 'IsPrinterOut = (e.PrintAction = Printing.PrintAction.PrintToPrinter)'
' gesetzt.
''' Beim Start des Druckauftrags werden die Vergleichsfelder SizeDispl und
' SizePrint sowie die Variable SizeFakt
''' auf SIZEF(0;0) zurückgesetzt. Dieser Nullwert ist das Kennzeichen, daß
' der in der Variablen SizeFakt
''' abgelegte Wert nicht aktuell ist und der Korrekturfaktor für das
' Ausgabemedium "Drucker" neu berechnet werden muß.
''' Jeweils der erste Aufruf der Funktion nach Start des Druckauftrages
' führt zur Berechnung des Korrekturfaktors.
''' Der so berechnete und in SizeFakt gespeicherte Korrekturfaktor wird für
' den gesamten Druckauftrag verwendet.</remarks> Die beiden Funktionen unterscheiden sich nur in der Ausführung des Parameters BREITE, der dem MEASURESTRING-Parameter WIDTH entspricht. Somit ist in den ersten drei Parametern der Systemfunktion die angestrebte Identität gegeben.
Diese Funktion habe ich an allen Stellen, an denen ich die Systemfunktion "MeasureString" aufrufe, eingefügt. Der zusätzliche Aufwand mit den auf Class-Ebene zu vereinbarenden drei Variablen erscheint mir vertretbar. Außerdem habe ich versucht die zusätzlich zu durchlaufenden Anweisungen und damit den zusätzlichen Zeitaufwand so gering wie möglich zu halten. Auch die Frage einer eventuellen Wertabweichung bei Wechsel des Druckers spielt keine Rolle, da er mit jedem Druckauftrag neu berechnet wird.
Es ist vielleicht nicht der optimale Code, aber ich bin erstmal zufrieden, eine wirksame Lösung gefunden zu haben. Denn jetzt entspricht auch die 99. Seite der Druckausgabe der Anzeige in der Vorschau. Ich bin jedem dankbar, der eine optimalere Lösungsvariante findet und diese hier veröffentlicht.
Ich habe versucht, den Programmcode so ausführlich wie möglich zu kommentieren. Dadurch erscheint dieser in der vorliegenden Zeilenlänge etwas unübersichtlich. Wenn aber, nach dem Kopieren auf IDE-Ebene die überzähligen Fortsetzungszeilen entfernt werden, glaube ich, daß der Code übersichtlich genug ist.
Ich danke allen, die sich an der Diskussion des Problems teilgenommen haben und wünsche Euch einen guten Rutsch ins neue Jahr.
Gruß, Rainer. | |
Re: Schrifthöhe mit Graphics-Funktion "MeasureString" für Display und Druck | | | Autor: Rainer | Datum: 25.12.17 13:04 |
| Hier die erste Variante:
''' <summary>
''' Misst die Zeichenfolge TEXT, wenn diese mit der angegebenen SCHRIFT
' dargestellt wird. Bei Vorgabe einer
''' verfügbaren BREITE des Darstellungsbereiches ist das Funktionsergebnis
' die erforderliche Bereichshöhe.
''' Mit Hilfe der Felder SizeDispl (Ausgabemdium "PrintPreviewControl") und
' SizePrint (Ausgabemedium "Drucker"), die
''' als Class-Variable im Datentyp SIZEF definiert sind, wird eine
' abweichende Berechnung der erforderlichen Breite
''' und Höhe ermittelt. Das Ausgabemedium "PrintPreviewControl" hat in
' diesem Vergleich das Primat. Der für das
''' Ausgabemedium "Drucker" mit der Graphics-Funktion MEASURSTRING
' ermittelte Wert wird mit dem in der Variablen
''' hinterlegten Korrekturfaktor angepaßt.
''' Die Funktion setzt voraus, daß jeder Ausgabe auf das Medium "Drucker"
' eine Ausgabe auf das Medium
''' "PrintPreviewControl" oder "PrintPreviewDialog" vorausgeht.
''' </summary>
''' <param name="Grafik">Verbindungsglied zum Ereignisargument e.Graphics
' in der Ereignisroutine PRINTDOCUMENT.PRINTPAGE</param>
''' <param name="Text">Der im Ausgabemedium darzustellende Text.</param>
''' <param name="Schrift">Die FONT-Einstellungen, die bei der
' TEXT-Darstellung Verwendung finden.</param>
''' <param name="Breite">Vorgabe einer einzuhaltenden maximalen Breite
' des Darstellungsbereiches in Grafikpunkte.
''' Ist die Vorgabe =-1, so wird die Breite den Anforderungen von TEXT und
' FONT in einzeiliger Darstellung berechnet.</param>
''' <returns>Beschreibung des Raumes (Höhe und Breite), der zur
' Darstellung von TEXT benötigt wird.</returns>
Friend Shared Function _MeasureStringKorr(ByVal Grafik As _
System.Drawing.Graphics, _
ByVal Text As String, _
ByVal Schrift As _
System.Drawing.Font, _
Optional ByVal Breite As Integer = _
-1) As SizeF
Dim _Font As System.Drawing.Font
Dim _Ber As SizeF
If (SizeFakt.Width = 0 And SizeFakt.Height = 0) Then ' Wurde
' der Korrekturfaktor bereits berechnet?
If Not IsPrinterOut AndAlso _
(SizeDispl.Width = 0 And SizeDispl.Height = 0) Then ' (
' NEIN) Musterwerte für PrintPreviewControl ermittelt?
_Font = New Font("Arial", 11, FontStyle.Regular) '
' (NEIN)
SizeDispl = Grafik.MeasureString("GM gm", _Font) '
' Musterwerte für PrintPreviewControl ermitteln
End If
If IsPrinterOut AndAlso _
(SizePrint.Width = 0 And SizePrint.Height = 0) Then ' (
' JA) Musterwerte für Drucker ermittelt?
_Font = New Font("Arial", 11, FontStyle.Regular) '
' (NEIN)
SizePrint = Grafik.MeasureString("GM gm", _Font) '
' Musterwerte für Drucker ermitteln
End If
If (SizeDispl.Width <> 0 And SizeDispl.Height <> 0) AndAlso _
(SizePrint.Width <> 0 And SizePrint.Height <> 0) Then _
' Musterwerte für die Ausgabemedien ermittelt?
SizeFakt.Width = ((SizeDispl.Width - SizePrint.Width) / _
SizePrint.Width) + 1 ' (NEIN) Korrekturfaktoren berechnen
SizeFakt.Height = ((SizeDispl.Height - SizePrint.Height) / _
SizePrint.Height) + 1
End If
End If
If IsPrinterOut Then '
' Ausgabemedium Drucker?
If (SizeFakt.Width <> 0 And SizeFakt.Height <> 0) Then _
' (JA) Wurde der Korrekturfaktor bereits berechnet?
If Breite > 0 Then _
' (JA) vorgegebene Druckbreite?
_Ber = Grafik.MeasureString(Text, Schrift, Breite / _
SizeFakt.Width) ' (JA)
Else
_Ber = Grafik.MeasureString(Text, Schrift) _
' (NEIN)
End If
Return New SizeF(_Ber.Width * SizeFakt.Width, _Ber.Height * _
SizeFakt.Height)
End If
End If
If Breite > 0 Then '
' vorgegebene Druckbreite?
Return Grafik.MeasureString(Text, Schrift, Breite) ' (
' JA)
Else
Return Grafik.MeasureString(Text, Schrift) ' (
' NEIN)
End If
End Function | |
Re: Schrifthöhe mit Graphics-Funktion "MeasureString" für Display und Druck | | | Autor: Rainer | Datum: 25.12.17 13:09 |
| und Variante 2:
''' <summary>
''' Misst die Zeichenfolge TEXT, wenn diese mit der angegebenen SCHRIFT
' dargestellt wird. Bei Vorgabe einer
''' verfügbaren BREITE des Darstellungsbereiches ist das Funktionsergebnis
' die erforderliche Bereichshöhe.
''' Mit Hilfe der Felder SizeDispl (Ausgabemdium "PrintPreviewControl") und
' SizePrint (Ausgabemedium "Drucker"), die
''' als Class-Variable im Datentyp SIZEF definiert sind, wird eine
' abweichende Berechnung der erforderlichen Breite
''' und Höhe ermittelt. Das Ausgabemedium "PrintPreviewControl" hat in
' diesem Vergleich das Primat. Der für das
''' Ausgabemedium "Drucker" mit der Graphics-Funktion MEASURSTRING
' ermittelte Wert wird mit dem in der Variablen
''' hinterlegten Korrekturfaktor angepaßt.
''' Die Funktion setzt voraus, daß jeder Ausgabe auf das Medium "Drucker"
' eine Ausgabe auf das Medium
''' "PrintPreviewControl" oder "PrintPreviewDialog" vorausgeht.
''' </summary>
''' <param name="Grafik">Verbindungsglied zum Ereignisargument e.Graphics
' in der Ereignisroutine PRINTDOCUMENT.PRINTPAGE</param>
''' <param name="Text">Der im Ausgabemedium darzustellende Text.</param>
''' <param name="Schrift">Die FONT-Einstellungen, die bei der
' TEXT-Darstellung Verwendung finden.</param>
''' <param name="Breite">Pflichtangabe eines einzuhaltenden Bereiches in
' Grafikpunkte.</param>
''' <returns>Beschreibung des Raumes (Höhe und Breite), der zur
' Darstellung von TEXT benötigt wird.</returns>
Friend Shared Function _MeasureStringKorr(ByVal Grafik As _
System.Drawing.Graphics, _
ByVal Text As String, _
ByVal Schrift As _
System.Drawing.Font, _
ByVal Breite As SizeF) As SizeF
Dim _Font As System.Drawing.Font
Dim _Ber As SizeF
If (SizeFakt.Width = 0 And SizeFakt.Height = 0) Then ' Wurde
' der Korrekturfaktor bereits berechnet?
If Not IsPrinterOut AndAlso _
(SizeDispl.Width = 0 And SizeDispl.Height = 0) Then ' (
' NEIN) Musterwerte für PrintPreviewControl ermittelt?
_Font = New Font("Arial", 11, FontStyle.Regular) '
' (NEIN)
SizeDispl = Grafik.MeasureString("GM gm", _Font) '
' Musterwerte für PrintPreviewControl ermitteln
End If
If IsPrinterOut AndAlso _
(SizePrint.Width = 0 And SizePrint.Height = 0) Then ' (
' JA) Musterwerte für Drucker ermittelt?
_Font = New Font("Arial", 11, FontStyle.Regular) '
' (NEIN)
SizePrint = Grafik.MeasureString("GM gm", _Font) '
' Musterwerte für Drucker ermitteln
End If
If (SizeDispl.Width <> 0 And SizeDispl.Height <> 0) AndAlso _
(SizePrint.Width <> 0 And SizePrint.Height <> 0) Then _
' Musterwerte für die Ausgabemedien ermittelt?
SizeFakt.Width = ((SizeDispl.Width - SizePrint.Width) / _
SizePrint.Width) + 1 ' (NEIN) Korrekturfaktoren berechnen
SizeFakt.Height = ((SizeDispl.Height - SizePrint.Height) / _
SizePrint.Height) + 1
End If
End If
If IsPrinterOut Then '
' Ausgabemedium Drucker?
If (SizeFakt.Width <> 0 And SizeFakt.Height <> 0) Then _
' (JA) Wurde der Korrekturfaktor bereits berechnet?
If (Breite.Width > 0 Or Breite.Height > 0) Then _
' (JA) vorgegebene Druckbreite?
_Ber = Grafik.MeasureString(Text, _
Schrift, _
New SizeF(Breite.Width / _
SizeFakt.Width, _
Breite.Height / _
SizeFakt.Height)) ' (JA)
Else
_Ber = Grafik.MeasureString(Text, Schrift) _
' (NEIN)
End If
Return New SizeF(_Ber.Width * SizeFakt.Width, _Ber.Height * _
SizeFakt.Height)
End If
End If
If (Breite.Width > 0 Or Breite.Height > 0) Then '
' vorgegebene Druckbreite?
Return Grafik.MeasureString(Text, Schrift, Breite) ' (
' JA)
Else
Return Grafik.MeasureString(Text, Schrift) ' (
' NEIN)
End If
End Function | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
sevISDN 1.0
Überwachung aller eingehender Anrufe!
Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Weitere InfosTipp des Monats Neu! sevDTA 3.0 Pro
SEPA mit Kontonummernprüfung
Erstellen von SEPA-Dateien mit integriertem BIC-Verzeichnis und Konto- nummern-Prüfverfahren, so dass ungültige Bankdaten bereits im Vorfeld ermittelt werden können. Weitere Infos
|