如何截断字符串以适合容器
本文关键字:何截断 字符串 | 更新日期: 2023-09-27 18:22:25
有很多问题(例如:1、2、3、4、5)询问如何将字符串截断为所需的字符数。但我想要一段被截断的文本,以便放在一个容器中。(IE:按字符串的宽度裁剪字符串,单位为像素,而非字符)。
如果你使用WPF,这很容易,但在WinForms中就不那么容易了。。。
那么:如何截断字符串以使其适合容器
经过一天的编码,我找到了一个解决方案,我想与社区分享它。
首先:对于字符串或winforms TextBox,没有本机截断函数。如果使用标签,则可以使用AutoEllipsis特性
仅供参考:省略号是由三个点组成的标点符号。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表单的命名空间中的类。请确保使用System.Drawing;包含""
这个类有两个扩展方法,都称为Truncate。基本上你现在可以这样做了:
public void textBox1_TextChanged(object sender, EventArgs e)
{
textBox1.Truncate();
}
您现在可以在textBox1中键入一些内容,如果需要,它会自动截断您的字符串以适应textBox,并添加省略号。
概述:该类目前包含3种方法:
- 截断(TextBox的扩展名)
- 截断(字符串的扩展名)
- MeasureString
截断(TextBox的扩展)
此方法将自动截断TextBox.Text属性。截断的方向由TextAlign属性决定。(例如:"左对齐的截断…","右对齐的截断"。)请注意:这种方法可能需要一些修改才能与其他书写系统(如希伯来语或阿拉伯语)一起使用
截断(字符串的扩展)
为了使用此方法,您必须传递两个参数:字体和所需宽度。字体用于计算字符串的宽度,所需的宽度用作截断后允许的最大宽度。
MeasureString
此方法在代码段中是私有的。所以,如果你想使用它,你必须先将其更改为公共。此方法用于以像素为单位测量字符串的高度和宽度。它需要两个参数:要测量的文本和文本的字体。
我希望我帮过别人。也许还有其他方法可以做到这一点,我发现Hans Passant的这个答案,它截断了一个ToolTipStatusLabel,这非常令人印象深刻。我的.NET技能与Hans Passant相去甚远,所以我还没有成功地将代码转换为使用TextBox之类的东西。。。但如果你真的成功了,或者有另一个解决方案,我很想看到它!:)
我测试了Jordy的代码,并将结果与我的代码进行了比较,没有差异,它们都可以修剪/截断,但在某些情况下不太好,这可能是MeasureString()
测量的大小不准确。我知道这段代码只是一个简化版本,如果有人关心它并使用它,我会把它发布在这里,因为它很短,而且我已经测试过了:与Jordy的代码相比,这段代码在修剪/截断字符串方面没有什么区别,当然,他的代码是某种完整版本,支持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.
}