Hallo,
gibt es in Net eine Möglichkeit die Länge eines Strings in Pixeln zu ermitteln? In Delphi kann man dazu den Canvas benutzen. Aber in Net hab ich bis jetzt noch nichts in der Richtung gefunden.
Viele Grüße
Thomas
Graphics g = Graphics.FromImage(myImage);
string myString = "Kann man die Länge eines String in Pixeln bestimmen?";
Font myFont = new Font("Arial Sans Ms", 12);
int myStringWidth = (int)g.MeasureString(myString, myFont).Width;
Mit anderen Worten: man kann.
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Danke 👍
Ich mach das jetzt so:
private int GetTextLengthInPixels(string myText)
{
Graphics g = Graphics.FromHwnd(this.Handle);
return (int)g.MeasureString(myText, tbMailText.Font).Width;
}
Da diese Funktion irgendwie die Länge von angehangenen Leerzeichen unterschlagen habe, bin ich über MeasureString auf TextRenderer gekommen. Damit wird auch die Länge der Leerzeichen zurück gegeben.
Hier die endgültige Funktion:
private int GetTextLengthInPixels(string myText)
{
return TextRenderer.MeasureText(Graphics.FromHwnd(tbMailText.Handle), myText, tbMailText.Font, new Size(int.MaxValue, int.MaxValue), TextFormatFlags.TextBoxControl).Width;
}
TextRenderer.MeasureText habe ich auch als praktischere Methode gefunden. Aber dazu gibt es auch eine Überladung, die nur mit Font und String arbeitet und auf Graphics und Controls verzichtet. Jürgen
Stimmt. Ich hatte mich zu sehr am Beispiel in der Hilfe orientiert. Danke für den Hinweis.
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
Btw.: Du solltest immer das Graphics-Objekt disposen, nachdem du es mit Graphics.FromHwnd() erzeugt hast, sonst kommt bald ein neuer Thread mit Titel "Hilfe Speicher läuft voll" hinzu 😁
Keine Angst, die Funktion habe ich schon dahingehend abgeändert, dass keine Graphics Objekt erforderlich ist.
Aber wieso eigentlich? Sollte da nicht die Garbage Collection greifen?
Nein. Auch in C# gibt es Objekte, die unmanaged Ressourcen nutzen. Beispiele: Dateien, Netzwerk/Sockets und eben auch deine Graphics Instanz.
Pound for pound, plutonium is about as toxic as caffeine when eaten.
So langsam bin ich ma verzweifeln ... ich versuch über die Textlänge eine Art Tabelle zu erstellen. Dabei fülle ich zu kleine Strings mit Tabs auf (Leerzeichen hab ich nicht in eine Reihe bekommen). Trotzdem gibt es noch einige wenige Ausreiser:
Funktion zum Textauffüllen:
private int GetPixelLength(string myText)
{
Graphics g = Graphics.FromHwnd(tbMailText.Handle);
int r = TextRenderer.MeasureText(g, myText, tbMailText.Font, new Size(int.MaxValue, int.MaxValue), TextFormatFlags.ExpandTabs | TextFormatFlags.TextBoxControl).Width;
g.Dispose();
return r;
}
private string GetStringToSize(string myText, int size)
{
while (GetPixelLength(myText) < size) { myText = myText + "\t"; }
return myText;
}
Mit TextFormatFlags.ExpandTabs | TextFormatFlags.TextBoxControl konnte ich es fast komplett korrigieren. Aber es wird bei 3 Zeilen von etwa 50 immer noch ein Tab zu viel eingefügt, obwohl die GetPixelLength am Ende bei allen Zeilen übereinstimmt. Irgendwie glaub ich, dass die Textbox die Tabs etwas anders interpretiert, als TextRenderer.MeasureText.
Hat jemand einen Lösungsvorschlag dafür?
Die erste Überladung von TextRenderer.MeasureText tut es auch, bzw. reicht aus.
int intWidth = TextRenderer.MeasureText("Hallo Welt", this.Font).Width;
intWidth = TextRenderer.MeasureText("Hallo Welt ", this.Font).Width;
intWidth = TextRenderer.MeasureText("Hallo Welt ", this.Font).Width;
intWidth = TextRenderer.MeasureText("Hallo Welt ", this.Font).Width;
Schau dir das mal im Debugger an. intWidth ist bei mir: 56,59,62 und 65. Die Leerzeichen werden also auch berücksichtigt! Ein Leerzeichen ist bei meiner Font Einstellung 3 Pixel breit.
Poste mal die 3 Teststrings wo ein Tab zu viel angehängt wird, sowie die größe von "size" in der while Schleife/Bedingung.
Wenn "size" zum Beispiel 100 Pixel ist und der String 90 Pixel ist und ein Tab 4 Pixel ist hast du einen Rest von PLUS 2 Pixel und zwei Tabs eingefügt, wenn Du auf 100 Pixel formatierst. Bei String 99 hast du einen Rest von PLUS 3 Pixel und einen Tab eingefügt. Ergo, jeder String der nicht durch 4 teilbar ist, paßt nach deinem Algorithmus nicht in die Formatierung bei size = 100 Pixel. Wenn du auf den Pixel genau formatieren willst mußt du selber zeichnen.
Vielleicht habe ich dich ja auch total falsch verstnaden, was du erreichen möchtest!
Wenn ja, kannst du mich ja ausführlichst aufklären. 🙂
So hatte ich es vorher, da wurden für einen Tab aber nur 10pixel berechnet. Nach dem Anfügen von TextFormatFlags.ExpandTabs wurde schonmal die richtige Tablänge verwendet (40pixel) aber es gab noch relativ viele Ausreiser mit zuviel Tabs. Mit TextFormatFlags.TextBoxControl wurde die Anzahl der Ausreiser auf 3 reduziert.
Size hat die Größe des größten Strings in der Spalte. Nach dem Durchlauf von GetStringToSize liefert GetPixelLength(myText) genau die Anzahl Pixel von Size zurück - anders ausgedrück nach dem Durchlauf von GetStringtoSize ist GetPixelLength(myText) = Size und das bei jedem Element. Und trotzdem scheint die Textbox, wo ich den zurückgelieferten String dann einfüge, die Tabs anders zu interpretieren, den nach dem Einfügen in die Textbox seh ich ja optisch, dass bei drei Zeilen 1 Tab zuviel ist, anders ausgedrück Optische Textlänge ist bei drei String != GetPixelLength(myText).
Ich teste mal weiter.
[Edit] ich habe mal einen Screenshot angehangen. Jede Spalte wird für sich berechnet(GetStringToSize) und am Ende zu einer Zeile zusammengefügt.
Hallo hitzi,
ist es für solch eine Darstellungsform nicht einfacher eine Schriftart festzulegen, die pro Zeichen eine feste Breite vorgibt? Dann kann man den Text Zeichenweise berechnen, und muss nicht mit Pixeln rechnen.
Wenn allerdings die Anforderungen bestimmen, dass man jegliche Schriftart nehmen können muss, dann ist dieser Tipp natürlich wertlos.
Gruß
Norman-Timo
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
So hab ich das früher in Delphi gemacht. Aber unter C#/Net hab ich noch keine Schriftart gefunden, die diesen Kriterium entspricht.
Natürlich Courier und Varianten; aber Standard für Controls ist nun mal Arial/Tahoma u.ä.
Siehe aber auch :rtfm: FontDescription.PitchAndFamily-Eigenschaft und PitchAndFamily-Enumeration
Gruß Jürgen
Danke dir. Ich hab aus irgendeinen Grund immer nur die San Serif Schriftarten auspropiert. Ich dachte die wären das gewesen.
Dann stell ich das mal wieder auf die Anzahl der zeichenfolge um und nicht mehr die Pixellänge.
Moin hitzi!
Und - haste es hinbekommen?
Grüsse - Kalle
Ja. Ich hab's jetzt so, wie in meinen letzten Post beschrieben gemacht. Erst Schriftart geändert und dann nicht mehr die Länge in Pixeln, sondern die Länge in Zeichen ermittelt. Die Pixellängen-Funktion konnte ich aber auch bei einer Tabelle(Listview) zur automatischen Spaltenanpassung weiter verwenden.
Gruss