Laden...

Textlänge in Pixeln?

Erstellt von hitzi vor 17 Jahren Letzter Beitrag vor 17 Jahren 17.807 Views
hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren
Textlänge in Pixeln?

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

3.003 Beiträge seit 2006
vor 17 Jahren

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)

hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

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; 
}
hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

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; 
        }
J
3.331 Beiträge seit 2006
vor 17 Jahren

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

hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

Stimmt. Ich hatte mich zu sehr am Beispiel in der Hilfe orientiert. Danke für den Hinweis.

3.825 Beiträge seit 2006
vor 17 Jahren

Siehe auch hier :

TextRenderer.MeasureText

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

M
1.439 Beiträge seit 2005
vor 17 Jahren

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 😁

hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

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?

D
386 Beiträge seit 2007
vor 17 Jahren

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.

hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

Gut zu wissen. Danke. 👍

hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

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?

230 Beiträge seit 2007
vor 17 Jahren

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. 🙂

hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

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.

4.506 Beiträge seit 2004
vor 17 Jahren

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!”

hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

So hab ich das früher in Delphi gemacht. Aber unter C#/Net hab ich noch keine Schriftart gefunden, die diesen Kriterium entspricht.

J
3.331 Beiträge seit 2006
vor 17 Jahren

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

hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

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.

230 Beiträge seit 2007
vor 17 Jahren

Moin hitzi!

Und - haste es hinbekommen?

Grüsse - Kalle

hitzi Themenstarter:in
125 Beiträge seit 2005
vor 17 Jahren

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