2013-07-15 33 views
7

文字列を希望の文字数に切り詰める方法については、多くの質問があります(EG:12345)。しかし、私は、コンテナに収まるように切り捨てられたテキストを必要とします。 (IE:巾をピクセル、でない文字列を切り抜く)。コンテナに収まるように文字列を切り詰めるには?

これはそう...

あなたがWPFを使用している場合は簡単ですが、リサイズではそれほどではない:はどのようにあなたはそれがコンテナに収まるようにするために、文字列を切り捨てることができますか?

答えて

13

コーディングの1日後、私は解決策を見つけ、コミュニティと共有したいと思っていました。

まずは文字列またはwinforms TextBoxのネイティブトランケート機能はありません。ラベルを使用する場合は、AutoEllipsisプロパティを使用できます。

FYI:省略記号は、3個のドットで構成さ句読点です。 IE:...

私はこれを作った理由です:

public static class Extensions 
{ 
    /// <summary> 
    /// Truncates the TextBox.Text property so it will fit in the TextBox. 
    /// </summary> 
    static public void Truncate(this TextBox textBox) 
    { 
     //Determine direction of truncation 
     bool direction = false; 
     if (textBox.TextAlign == HorizontalAlignment.Right) direction = true; 

     //Get text 
     string truncatedText = textBox.Text; 

     //Truncate text 
     truncatedText = truncatedText.Truncate(textBox.Font, textBox.Width, direction); 

     //If text truncated 
     if (truncatedText != textBox.Text) 
     { 
      //Set textBox text 
      textBox.Text = truncatedText; 

      //After setting the text, the cursor position changes. Here we set the location of the cursor manually. 
      //First we determine the position, the default value applies to direction = left. 

      //This position is when the cursor needs to be behind the last char. (Example:"…My Text|"); 
      int position = 0; 

      //If the truncation direction is to the right the position should be before the ellipsis 
      if (!direction) 
      { 
       //This position is when the cursor needs to be before the last char (which would be the ellipsis). (Example:"My Text|…"); 
       position = 1; 
      } 

      //Set the cursor position 
      textBox.Select(textBox.Text.Length - position, 0); 
     } 
    } 

    /// <summary> 
    /// Truncates the string to be smaller than the desired width. 
    /// </summary> 
    /// <param name="font">The font used to determine the size of the string.</param> 
    /// <param name="width">The maximum size the string should be after truncating.</param> 
    /// <param name="direction">The direction of the truncation. True for left (…ext), False for right(Tex…).</param> 
    static public string Truncate(this string text, Font font, int width, bool direction) 
    { 
     string truncatedText, returnText; 
     int charIndex = 0; 
     bool truncated = false; 
     //When the user is typing and the truncation happens in a TextChanged event, already typed text could get lost. 
     //Example: Imagine that the string "Hello Worl" would truncate if we add 'd'. Depending on the font the output 
     //could be: "Hello Wor…" (notice the 'l' is missing). This is an undesired effect. 
     //To prevent this from happening the ellipsis is included in the initial sizecheck. 
     //At this point, the direction is not important so we place ellipsis behind the text. 
     truncatedText = text + "…"; 

     //Get the size of the string in pixels. 
     SizeF size = MeasureString(truncatedText, font); 

     //Do while the string is bigger than the desired width. 
     while (size.Width > width) 
     { 
      //Go to next char 
      charIndex++; 

      //If the character index is larger than or equal to the length of the text, the truncation is unachievable. 
      if (charIndex >= text.Length) 
      { 
       //Truncation is unachievable! 

       //Throw exception so the user knows what's going on. 
       throw new IndexOutOfRangeException("The desired width of the string is too small to truncate to."); 
      } 
      else 
      { 
       //Truncation is still applicable! 

       //Raise the flag, indicating that text is truncated. 
       truncated = true; 

       //Check which way to text should be truncated to, then remove one char and add an ellipsis. 
       if (direction) 
       { 
        //Truncate to the left. Add ellipsis and remove from the left. 
        truncatedText = "…" + text.Substring(charIndex); 
       } 
       else 
       { 
        //Truncate to the right. Remove from the right and add the ellipsis. 
        truncatedText = text.Substring(0, text.Length - charIndex) + "…"; 
       } 

       //Measure the string again. 
       size = MeasureString(truncatedText, font); 
      } 
     } 

     //If the text got truncated, change the return value to the truncated text. 
     if (truncated) returnText = truncatedText; 
     else returnText = text; 

     //Return the desired text. 
     return returnText; 
    } 

    /// <summary> 
    /// Measures the size of this string object. 
    /// </summary> 
    /// <param name="text">The string that will be measured.</param> 
    /// <param name="font">The font that will be used to measure to size of the string.</param> 
    /// <returns>A SizeF object containing the height and size of the string.</returns> 
    static private SizeF MeasureString(String text, Font font) 
    { 
     //To measure the string we use the Graphics.MeasureString function, which is a method that can be called from a PaintEventArgs instance. 
     //To call the constructor of the PaintEventArgs class, we must pass a Graphics object. We'll use a PictureBox object to achieve this. 
     PictureBox pb = new PictureBox(); 

     //Create the PaintEventArgs with the correct parameters. 
     PaintEventArgs pea = new PaintEventArgs(pb.CreateGraphics(), new System.Drawing.Rectangle()); 
     pea.Graphics.PageUnit = GraphicsUnit.Pixel; 
     pea.Graphics.PageScale = 1; 

     //Call the MeasureString method. This methods calculates what the height and width of a string would be, given the specified font. 
     SizeF size = pea.Graphics.MeasureString(text, font); 

     //Return the SizeF object. 
     return size; 
    } 
} 

用途: これは、あなたがコピーしてお使いのWinFormsフォームが含まれている名前空間に貼り付けることができたクラスです。 "using System.Drawing;"

このクラスには、両方ともトランケートと呼ばれる2つの拡張メソッドがあります。基本的に、あなたは今、これを行うことができます。

public void textBox1_TextChanged(object sender, EventArgs e) 
{ 
    textBox1.Truncate(); 
} 

あなたは今、textBox1テキストボックスに何かを入力することができ、必要であれば、それは自動的にテキストボックスに収まるように、あなたの文字列が切り捨てられますし、それが省略記号を追加します。

概要: このクラスは、現在3つのメソッドが含まれています

  1. 切り捨て(TextBoxのための拡張)
  2. 切り捨て(文字列の拡張子)
  3. MeasureString

切り捨て(TextBoxの拡張)

このメソッドは自動的にTextBox.Textプロパティを切り捨てます。切り捨ての方向は、TextAlignプロパティによって決まります。 (EG:「左揃えの切り捨て」...「右揃えの...」)注意:このメソッドは、ヘブライ語やアラビア語などの他の書記体系で使用するには、いくつかの変更が必要な場合があります。


トランケート(文字列の拡張)

次の2つのパラメータを渡す必要があり、この方法で使用するために:フォントと所望の幅を。フォントは文字列の幅を計算するために使用され、目的の幅は切り捨て後に許容される最大幅として使用されます。


この方法

をMeasureStringコードスニペットでプライベートです。だからあなたがそれを使いたいなら、それを最初にpublicに変更しなければなりません。このメソッドは、文字列の高さと幅をピクセル単位で測定するために使用されます。これには、測定するテキストとテキストのフォントの2つのパラメータが必要です。

私はこのことを誰かに助けてくれることを願っています。おそらく、これを行う別の方法があります、私はかなり印象的なToolTipStatusLabelを切り捨てるHans Passantによってthisの答えが見つかりました。私の.NETのスキルはHans Passantのどこにもありませんので、TextBoxのようなもので動作するようにコードを変換することはできませんでした...しかし、suceeedした場合や、別の解決策がある場合は、 :)

+1

+1あなたのソリューションに関する素晴らしいドキュメント。しかし、このアプローチは文字通り 'TextBox'のテキストを変更します。もちろん、 'Tag'のような他のプロパティを使って管理することもできますが、Hansの答えは' Paint'プロシージャを単にオーバーライドします。これは 'Text'だけを残しますが、テキストが切り捨てられた*錯覚*をユーザーに提供します。 –

+0

@MichaelPerrenoudそれは確かに注目に値する。そして、私がハンス・パッセンツの答えに言及した理由も。それはただよりエレガントです:) – Jordy

+1

しかし、いくつかの研究の後で、テキストボックスに何かを描くことは本当にカスタムできないということです。だから私はあなたが必要とするもので、あなたができる最高のやり方をしたと言います。素晴らしい仕事! –

0

私はジョーディのコードをテストし、結果をこのコードと比較しましたが、違いはありませんが、両方ともトリミング/切り詰めがかなりうまくいく場合もありますが、それはMeasureString()正確ではない。私はこのコードが単なる単純化されたバージョンであることを知っています。誰かが気にしてそれを使うのであれば、ここに投稿します。もちろん、彼のコードは、3つのメソッドがサポートされたフルバージョンの何らかの種類です。

public static class TextBoxExtension 
{ 
    public static void Trim(this TextBox text){    
     string txt = text.Text; 
     if (txt.Length == 0 || text.Width == 0) return; 
     int i = txt.Length;    
     while (TextRenderer.MeasureText(txt + "...", text.Font).Width > text.Width)    
     { 
      txt = text.Text.Substring(0, --i); 
      if (i == 0) break; 
     } 
     text.Text = txt + "..."; 
    } 
    //You can implement more methods such as receiving a string with font,... and returning the truncated/trimmed version. 
} 
関連する問題