2016-03-28 7 views
3

Ich habe eine benutzerdefinierte abgerundete Textbox, und ich möchte nicht Text in abgerundete Teile schreiben, also möchte ich wissen, wie viele Zeichen vom Anfang der Zeichenfolge eine angegebene mit erreichen. Ich weiß, TextRenderer.MeasureText, um eine Zeichenfolge zu messen, aber es gibt nur die Breite einer Zeichenfolge, funktioniert nicht umgekehrt. Wie kann ich das machen?Wie erhält man einen Stringteil nach einem Breitenwert?

Ich kann das tun, aber es kann manchmal viel Zeit dauern.

string resultText = string.Empty; 

    for (int i = 0; i < Text.Length; i++) 
    { 
     resultString = Text.Substring(0, i); 
     if (TextRenderer.MeasureText(resultText, Font).Width <= textWidth) 
      break; 
    } 
+1

welche Art von Anwendung ist das? Verwenden Sie ordnungsgemäßes Tagging –

+0

Dies ist eine Windows Form Application –

+0

Sofern Sie nicht eine Schriftart mit fester Breite verwenden, haben alle Zeichen unterschiedliche Breiten, so etwas wie das ist, was Sie tun müssen. – TaW

Antwort

0

Ich habe eine bessere Lösung ohne Schleife gefunden. Bei dieser Methode berechnen wir ein Verhältnis zwischen aktueller Breite und Zielbreite. Und wenn dieses Verhältnis mit der aktuellen Länge der Zeichenfolge multipliziert wird, erhalten wir einen guten Teilzeichenfolgepunkt.

string GetSubStringToWidth(string orgText, int width, Font font) 
    { 
     int orgWidth = TextRenderer.MeasureText(orgText, font).Width; 

     float ratio = (float)width/orgWidth; 

     int length = (int)(orgText.Length * ratio); 

     if (length >= orgText.Length) return orgText; 
     else if (length <= 0) return ""; 
     else 
     { 
      //May be more sensitive if we go right or left one unit because of letter unequalities 
      int mid = Math.Abs(width - TextRenderer.MeasureText(orgText.Substring(0, length), font).Width); 
      int right = Math.Abs(width - TextRenderer.MeasureText(orgText.Substring(0, length + 1), font).Width); 
      int left = Math.Abs(width - TextRenderer.MeasureText(orgText.Substring(0, length - 1), font).Width); 

      int i = Math.Min(Math.Min(mid, right), left); 
      int point = 0; 

      if (i == mid) 
       point = length; 
      else if (i == right) 
       point = length + 1; 
      else 
       point = length - 1; 

      return orgText.Substring(0, point); 
     } 
    } 
+0

Ich bezweifle, dass dies auf alle Arten von Inhalt gut funktioniert. Ich bezweifle auch, dass Ihre Sorgen über das Timing keinen wirklichen Grund haben. "Vorzeitige Optimierung ist die Wurzel allen Übels". Und natürlich wird das Abschneiden von Text normalerweise dazu führen, dass Text abgeschnitten wird. – TaW

+0

Ich habe es nur in meinem Code getestet. Es hat den Text in der Mitte des Textfelds gesetzt und das war was ich will. Ich bin mir nicht sicher, ob es bei allen Inhalten gut funktioniert, aber je besser, desto besser. –