| |
VB.NET - Ein- und UmsteigerGenaue Breite eines Strings ermitteln | | | Autor: Kalli | Datum: 30.05.18 17:57 |
| Ich versuche vergeblich in VB Net die genaue Breite eines Strings in Pixeln zu ermitteln. Wie ich die Suche danach auch anstelle, ich lande immer bei einer Form von "MeasureText", was als size nur eine ungenaue Höhe und Breite liefert, sodass man z.B. in einer PictureBox keine Chance hat, ein Caret genau hinter einen existierenden Grafiktext zu platzieren. Zur Bestimmung der minimalen Texthöhe gibt es einige Texteigenschaften, die man von der durch "MeasureText" gelieferten Höhe abziehen kann, aber für die Textbreite scheinen solche Regularien in VB Net vollkommen zu fehlen.
Könnt Ihr mir helfen?
Dont debug, because there will allways be one more bug | |
Re: Genaue Breite eines Strings ermitteln | | | Autor: Manfred X | Datum: 30.05.18 19:32 |
| Hallo!
Probiere mal so ...
Public Class frmTextWidth
Dim pb As New PictureBox With {.Parent = Me, .Dock = DockStyle.Fill}
Dim bmp As New Bitmap(300, 300)
Private Sub frmTextWidth_Load(sender As Object, _
e As EventArgs) Handles MyBase.Load
Dim txt As String = "Irgendein Text"
Dim fo As New Font("Arial", 14, FontStyle.Bold)
Using gr As Graphics = Graphics.FromImage(bmp),
br As New SolidBrush(Color.Black)
With gr
.Clear(Color.White)
.DrawString(txt, fo, br, New Point(20, 20))
Dim ts As SizeF = .MeasureString(txt, fo)
.FillRectangle(br, ts.Width + 20, 20, ts.Height, ts.Height)
End With
End Using
pb.Image = bmp
End Sub
End Class Bei einem mehrzeiligen oder umbrochenen Text könntest Du jede Zeile
einzeln in der Box plazieren und ausmessen.
Beitrag wurde zuletzt am 30.05.18 um 19:39:28 editiert. | |
Re: Genaue Breite eines Strings ermitteln | | | Autor: Kalli | Datum: 30.05.18 20:08 |
| Vielen Dank für Deine Mühe. Das Problem ist, dass Du auch von "MeasureText" ausgehst, was eine zu große Breite liefert.
Ich komme mit Deinem gefüllten Rechteck nicht so ganz klar: Breite und Höhe gleich?
.FillRectangle(br, ts.Width + 20, 20, ts.Height, ts.Height) Aber selbst, wenn Du Dich vertippt hast und meinst:
.FillRectangle(br, ts.Width + 20, 20, ts.Width, ts.Height) ist die size "ts" nicht genau passend, sondern etwas zu groß. Das ist genau mein Problem.
Ich habe versucht, das Problem zu lösen, indem ich den Text schwarz mit schwarzem Hintergrund auf eine weiße Bitmap schreibe und dann die schwarzen Pixel in Höhe und Breite auslese. Das liefert mir das exakte Ergebnis, könnte aber bei einem langsamen Rechner zu Verzögerungen bei der Texteingabe führen.
Kalle
Dont debug, because there will allways be one more bug | |
Re: Genaue Breite eines Strings ermitteln | | | Autor: Kalli | Datum: 31.05.18 00:18 |
| Hallo Manfred X,
vielen Dank. Da war ich schon, habe aber nicht alles verstanden. Zum Probieren bin ich noch nicht gekommen. Ich werde es die Tage nach Deinem Vorschlag nochmal durchprobieren und bei Erfolg hier posten.
Dont debug, because there will allways be one more bug | |
Re: Genaue Breite eines Strings ermitteln | | | Autor: Kalli | Datum: 01.06.18 08:54 |
| Hallo Manfred X,
entschuldige die späte Antwort, war zu sehr mit Brötchen verdienen beschäftigt.
Ich habe den Unterschied zwischen TextRenderer.MeasureText und Grapics.MeasureString ausprobiert. Es bringt leider nur ein paar Pixel, aber in der Bemessung der Textbreite nicht genau den Punkt, wo der nächste Buchstabe eines neuen Strings ansetzen müsste.
Hier der Code, den ich zum Ausprobieren benutzt habe:
Public Class Form1
Dim s As String, fo As Font
Private Sub Bild_Paint(sender As Object, e As PaintEventArgs) Handles _
Bild.Paint
Dim hdc As IDeviceContext
hdc = e.Graphics
fo = New Font("Calligraph421 BT", 40, FontStyle.Regular)
s = "Alle meine Entchen"
Dim si As Size = TextRenderer.MeasureText(s, fo)
Dim si1 As SizeF = e.Graphics.MeasureString(s, fo)
Debug.Print(si.Width.ToString + " " + si.Height.ToString)
Dim bm As New Bitmap(Bild.Width, Bild.Height)
Bild.Image = bm
Using gr As Graphics = Graphics.FromImage(Bild.Image)
gr.DrawString(s, fo, Brushes.Black, New Point(0, 0))
gr.DrawRectangle(Pens.Red, New Rectangle(0, 0, si1.Width, _
si1.Height))
TextRenderer.DrawText(gr, s, fo, New Point(0, 40), Color.Black)
gr.DrawRectangle(Pens.Red, New Rectangle(0, 40, si.Width, _
si.Height))
End Using
End Sub
End Class Ich werde aber noch weiter herumprobieren (In GFA-Basic hatte ich dafür eine Methode "Text.Width", die die exakte Breite lieferte, "Text.Height" lieferte einen sauberen Zeilenabstand ohne viel Klimbim)
Bis ev. in ein paar Tagen, hab so viel anderes Zeug um die Ohren.
Kalle
Dont debug, because there will allways be one more bug | |
Re: Genaue Breite eines Strings ermitteln | | | Autor: GPM | Datum: 01.06.18 13:07 |
| Mal mit TextFormatFlags.NoPadding testen:
Public Class Form1
Dim WithEvents Pb As New PictureBox With {.Dock = DockStyle.Fill, _
.BackColor = Color.Black, .Parent = Me}
Dim Fo As New Font("Arial", 40)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Width = 700
End Sub
Private Sub Pb_Paint(sender As Object, e As PaintEventArgs) Handles Pb.Paint
Dim str As String = "ABCD56789 i Q y {}³z", s = "", sz As Size
For i = 1 To str.Length
s = str.Substring(0, i)
sz = TextRenderer.MeasureText(e.Graphics, s, Fo, New Size, _
TextFormatFlags.NoPadding)
TextRenderer.DrawText(e.Graphics, s, Fo, New Point(0, 0), _
Color.Yellow, TextFormatFlags.NoPadding)
e.Graphics.DrawRectangle(Pens.White, New Rectangle(New Point(0, 0), _
sz))
Next
End Sub
End Class MfG GPM | |
Re: Genaue Breite eines Strings ermitteln | | | Autor: Kalli | Datum: 01.06.18 16:44 |
| Danke GPM,
hörte sich toll an, aber das "NoPadding" wirkt sich leider nicht auf MeasureText aus. Das angezeigte umschließende Rechteck verändert seine Größe nicht. Was ich brauche, sind die Maße in Pixeln (oder sonst etwas) die das Recheck hat, welches den Texthintergrund bildet. Bis jetzt bin ich immer noch beim Auszählen der Pixel des Hintergrundrechtecks.
Using gr As Graphics = Graphics.FromImage(Bild.Image)
Dim si As Size = TextRenderer.MeasureText(s, fo, New Size, _
TextFormatFlags.NoPadding)
TextRenderer.DrawText(gr, s, fo, New Point(0, 0), Color.Black, _
Color.White, TextFormatFlags.NoPadding)
gr.DrawRectangle(Pens.Red, New Rectangle(0, 0, si.Width, si.Height))
End Using Kalle
Dont debug, because there will allways be one more bug | |
Re: Genaue Breite eines Strings ermitteln | | | Autor: GPM | Datum: 01.06.18 18:21 |
| Es entspricht aber auch nicht meinem Beispiel (gr fehlt)
Public Class Form1
Dim WithEvents Pb As New PictureBox With {.Dock = DockStyle.Fill, _
.BackColor = Color.Black, .Parent = Me}
Dim Fo As New Font("Arial", 40)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Width = 700
End Sub
Private Sub Pb_Paint(sender As Object, e As PaintEventArgs) Handles Pb.Paint
Dim s As String = "Alle meine Entchen"
Dim gr As Graphics = e.Graphics
Dim si As Size = TextRenderer.MeasureText(s, Fo, New Size, _
TextFormatFlags.NoPadding)
TextRenderer.DrawText(gr, s, Fo, New Point(0, 0), Color.Black, _
Color.White, TextFormatFlags.NoPadding)
gr.DrawRectangle(Pens.Red, New Rectangle(0, 0, si.Width, si.Height))
si = TextRenderer.MeasureText(gr, s, Fo, New Size, _
TextFormatFlags.NoPadding)
TextRenderer.DrawText(gr, s, Fo, New Point(0, 100), Color.Yellow, _
Color.Blue, TextFormatFlags.NoPadding)
gr.DrawRectangle(Pens.White, New Rectangle(0, 100, si.Width, si.Height))
End Sub
End Class MfG GPM | |
Re: Genaue Breite eines Strings ermitteln | | | Autor: Kalli | Datum: 01.06.18 18:59 |
| Wow - mit dem Device-Context klappt es!!!!!(hatte ich übersehen.)
Danke! Die so ermittelte Textbreite und -Höhe entspricht genau dem Hintergrund.
Hier nochmal das Wesentliche für alle, die das gleiche Problem haben:
Using gr As Graphics = Graphics.FromImage(Bild.Image)
Dim si As Size = TextRenderer.MeasureText(gr, s, fo, New Size, _
TextFormatFlags.NoPadding)
TextRenderer.DrawText(gr, s, fo, New Point(0, 0), Color.Black, _
Color.White, TextFormatFlags.NoPadding)
'gr.DrawString(s, fo, Brushes.Black, New Point(0, 0)) nicht
' benutzen!
gr.DrawRectangle(Pens.Red, New Rectangle(0, 0, si.Width, si.Height))
End Using "Bild" = PictureBox
"s"= String
"fo" = Font
Achtung! Mit "gr.DrawString" funktioniert es nicht! Das sind zwei Welten.
Kalle
Dont debug, because there will allways be one more bug | |
| 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
|