Rubrik: Grafik und Font · Font & Text | VB-Versionen: VB2008, VB2010, VB2012 | 18.02.14 |
Umbrechen langer Strings mittels Measurement-Methode und speziellen Funktionen Der Tipp befasst sich mit dem Umbrechen von langen Strings bei Anwendung der Funktion DrawString. Es wird eine vorgegebene Breite (evtl. Breite des Ausgaberechtecks) und der anzuwendende Font beachtet. | ||
Autor: Dietrich Herrmann | Bewertung: | Views: 7.784 |
ohne Homepage | System: Win7, Win8, Win10, Win11 | kein Beispielprojekt |
Für das Vorbereiten von langen Strings für das Drucken stieß ich auf das Problem, dass bei Anwendung der Funktion DrawString mittels StringFormat nur die Option WordWrap zur Verfügung steht, d.h., lange Strings werden da automatisch, optimal bei Auftreten von Leerzeichen umgebrochen. In meinem Fall traten aber lange Strings (bspw. Verzeichnisnamen) auf, die keinerlei Leerzeichen enthielten. Deshalb musste ich nach Möglichkeiten suchen, den Umbruch anders zu gewährleisten.
Zwei Möglichkeiten und deren Kombination habe ich dazu entwickelt. Die erste Funktion, die ich zeige, ist gewissermaßen eine Hilfsfunktion, die in den weiteren Funktionen verwendet wird. Sie erzeugt einen Teilstring des Originalstrings mittels der Measurement-Methode:
''' <summary> ''' Teilstring eines Strings gemäß Measurement-Methode ''' </summary> ''' <param name="theStr">der String</param> ''' <param name="theFont">der Font</param> ''' <param name="theWidth">die maximal zur Verfügung stehende Breite</param> ''' <param name="g">Graphicsobjekt, auf das der String ausgegeben wird</param> ''' <param name="beginChar">Index des ersten zeichens, ab dem die Breite gemessen wird</param><returns ''' <returns>den Teil eines Strings, der eine vorgegebene Breite einhält und ''' den Index des letzten Zeichens im Originalstring</returns> Public Function getPartialString( _ theStr As String, theFont As Font, theWidth As Single, _ g As Graphics, Optional beginChar As Short = 0) As Tuple(Of String, Short) Dim actS As SizeF, i, j As Short, strTemp As String ' Vom Index eines bestimmten Zeichens an bis zum String-Ende ' einen Teilstring erzeugen, der immer um ein Zeichen ergänzt wird. ' Den erzeugten Teilstring nach seiner Breite messen und wenn Breite überschritten ' wird, den passenden Teilstring und den Index des letzten Zeichens ausgeben. For i = beginChar To theStr.Length - 1 strTemp = theStr.Substring(beginChar, j) actS = g.MeasureString(strTemp, theFont) If actS.Width >= theWidth Then Exit For j += 1 Next If i = theStr.Length Then strTemp = theStr.Substring(beginChar) i = -1 ' Index für letzten Teilstring, wenn Teilstring kürzer als vorgegebene Breite End If Return New Tuple(Of String, Short)(strTemp, i) End Function
Die zweite Funktion erzeugt ein Feld der Teilstrings eines Originalstrings. Diese Teilstrings "passen" jeder für sich in die vorgegebene Breite. Mit einfachem Join-Befehl können die Teilstrings unter Verwendung eines Umbruchzeichens (vbCrLf) wieder zusammengesetzt und dann mittels Drawstring ausgegeben werden.
''' <summary> ''' Erzeugen eines Felds von Teilstrings eines Strings gemäß Measurement-Methode ''' </summary> ''' <param name="theStr">der String</param> ''' <param name="theFont">der Font</param> ''' <param name="theWidth">die maximal zur Verfügung stehende Breite</param> ''' <param name="g">Graphicsobjekt, auf das der String ausgegeben wird</param> ''' <returns>ein Feld mit den Teilstrings eines strings, die eine vorgegebene Breite einhalten</returns> Public Function splitStringMeasurement( _ theStr As String, theFont As Font, theWidth As Single, g As Graphics) As String() Dim strTemp As Tuple(Of String, Short), j, i As Short Dim sp() As String 'das Ausgabefeld mit den Teilstrings i = 0 : j = 0 Do strTemp = getPartialString(theStr, theFont, theWidth, g, i) 'einen Teilstring ermitteln ReDim Preserve sp(j) ' Teilstring ins Feld speichern sp(j) = strTemp.Item1 ' letzten Index des Teilstrings als Anfangsindex für nächsten Teilstring verwenden i = strTemp.Item2 j += 1 Loop Until i < 0 Return sp 'Rückgabe des Teilstring-Feldes End Function
Die dritte hier gezeigte Funktion realisiert das Umbrechen von langen Strings eben nicht am Leerzeichen (WordWrap) sondern an einem selbst vorgegebenem Zeichen (bspw. \). Die Zeilen werden dabei immer so in der Breite eingepasst, dass das spezielle Zeichen den Abschluss der Zeile bildet.
''' <summary> ''' Umbrechen eines Strings, ''' nach einem speziellen Zeichen ''' </summary> ''' <param name="theStr">der String</param> ''' <param name="theFont">der Font</param> ''' <param name="theWidth">die maximal zur Verfügung stehende Breite</param> ''' <param name="g">Graphicsobjekt, auf das der String ausgegeben wird</param> ''' <param name="insStr">der String zum Einfügen an der 'Wrap-Stelle' (Standard: Zeilenumbruch)</param> ''' <param name="specChar">das spezielle Zeichen</param> ''' <returns>den umgebrochenen String</returns> Public Function wrapStringSpecChar( _ theStr As String, _ theFont As Font, _ theWidth As Single, _ g As Graphics, _ Optional insStr As String = vbCrLf, _ Optional specChar As String = "\") As String Dim actS As SizeF, i, j As Short, strTempL As String Dim spt() As String Dim sp() As String = Split(theStr, specChar) 'splitten nach speziellem Zeichen ' überprüfen aller "Unterstrings (ohne speziellem Zeichen)" auf Länge ' und Einfügen von Zeilenumbruch, wenn notwendig For i = 0 To sp.Length - 1 strTempL = sp(i) + If(i < sp.Length - 1, specChar, "") spt = splitStringMeasurement(strTempL, theFont, theWidth, g) strTempL = Join(spt, insStr) sp(i) = strTempL Next strTempL = "" For i = 0 To sp.Length - 1 strTempL += sp(i) ' messen des gekürzten Strings If i < sp.Length - 1 Then actS = g.MeasureString(strTempL + sp(i + 1), theFont) ' prüfen, ob gekürzter String in der Länge passt If actS.Width > theWidth Then strTempL += insStr 'Umbruchzeichen einfügen ' Rest anfügen For j = i + 1 To sp.Length - 1 strTempL += sp(j) Next theStr = strTempL Exit For End If End If Next Return theStr End Function
Zwei Beispiele des Aufrufs:
Die Beispiele arbeiten beide mit den jeweiligen optionalen Satndardvorgaben für inStr und specChar.
(myText.. der umzubrechende String, the_font.. der anzuwendende Font, layout_rect.. das Rechteck, in das der String eingepasst werden soll,
e.Graphics.. das Graphics-Objekt in das der String ausgegeben werden soll)
1. Einfacher Umbruch, wenn vorgegebene Breite erreicht
myText = Join(splitStringMeasurement(myText, the_font, layout_rect.Width, e.Graphics), vbCrLf)
2. Umbruch mittels speziellem Zeichen
myText = wrapStringSpecChar(myText, the_font, layout_rect.Width, e.Graphics)