Word在多行中包装一个string

我试图把一个string换成多行。 每一行都有定义的宽度。

例如,如果我把它换成宽度为120像素的区域,我会得到这个结果。

Lorem ipsum dolor坐amet,
consectetur adipiscing elit。 Sed augue
velit,tempor non vulputate sit amet,
单字lacus的中英文例句与用法 在个人身上
justo,ut accumsan sem。 Donec
pulvinar,nisi nec sagittis consequat,
sem orci luctus velit,sed elementum
ligula没有必要。 Pellentesque
居民morbi tristique senectus et
netus和malesuada fames ac turpis
egestas。 Etiam erat est,pellentesque
eget tincidunt ut,egestas in ante。
Nulla vitae vulputate velit。 Proin in
conque neque。 Cras rut​​rum sodales
sapien,ut convallis erat auctor vel。
Duis ultricies pharetra dui,sagittis
varius mauris tristique a。 Nam ut
neque id risus tempor hendrerit。
Maecenas ut lacus nunc。 法无
fermentum ornare rhoncus。 法无
gravida vestibulum odio,vel商品
大蒜调味品。 Quisque
sollicitudin blandit mi,非varius
libero lobortis eu。 Vestibulum欧盟
turpis massa,id tincidunt orci。
Curabitur pellentesque urna非risus
adipiscing facilisis。 Mauris vel
accumsan purus。 Proin quis enim nec
sem tempor vestibulum ac vitae augue。

static void Main(string[] args) { List<string> lines = WrapText("Add some text", 300, "Calibri", 11); foreach (var item in lines) { Console.WriteLine(item); } Console.ReadLine(); } static List<string> WrapText(string text, double pixels, string fontFamily, float emSize) { string[] originalLines = text.Split(new string[] { " " }, StringSplitOptions.None); List<string> wrappedLines = new List<string>(); StringBuilder actualLine = new StringBuilder(); double actualWidth = 0; foreach (var item in originalLines) { FormattedText formatted = new FormattedText(item, CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(fontFamily), emSize, Brushes.Black); actualLine.Append(item + " "); actualWidth += formatted.Width; if (actualWidth > pixels) { wrappedLines.Add(actualLine.ToString()); actualLine.Clear(); actualWidth = 0; } } if(actualLine.Length > 0) wrappedLines.Add(actualLine.ToString()); return wrappedLines; } 

添加WindowsBasePresentationCore库。

下面的代码,从这个博客post ,将有助于完成你的工作。

你可以这样使用它:

 string wordWrappedText = WordWrap( <yourtext>, 120 ); 

请注意,代码不是我的,我只是在这里报告你的商品的主要function。

 protected const string _newline = "\r\n"; public static string WordWrap( string the_string, int width ) { int pos, next; StringBuilder sb = new StringBuilder(); // Lucidity check if ( width < 1 ) return the_string; // Parse each line of text for ( pos = 0; pos < the_string.Length; pos = next ) { // Find end of line int eol = the_string.IndexOf( _newline, pos ); if ( eol == -1 ) next = eol = the_string.Length; else next = eol + _newline.Length; // Copy this line of text, breaking into smaller lines as needed if ( eol > pos ) { do { int len = eol - pos; if ( len > width ) len = BreakLine( the_string, pos, width ); sb.Append( the_string, pos, len ); sb.Append( _newline ); // Trim whitespace following break pos += len; while ( pos < eol && Char.IsWhiteSpace( the_string[pos] ) ) pos++; } while ( eol > pos ); } else sb.Append( _newline ); // Empty line } return sb.ToString(); } /// <summary> /// Locates position to break the given line so as to avoid /// breaking words. /// </summary> /// <param name="text">String that contains line of text</param> /// <param name="pos">Index where line of text starts</param> /// <param name="max">Maximum line length</param> /// <returns>The modified line length</returns> public static int BreakLine(string text, int pos, int max) { // Find last whitespace in line int i = max - 1; while (i >= 0 && !Char.IsWhiteSpace(text[pos + i])) i--; if (i < 0) return max; // No whitespace found; break at maximum length // Find start of whitespace while (i >= 0 && Char.IsWhiteSpace(text[pos + i])) i--; // Return length of text before whitespace return i + 1; } 

这里是我为我的XNA游戏提出的一个版本…

(请注意,这是一个片段,不是一个合适的类定义,请享用!)

 using System; using System.Text; using Microsoft.Xna.Framework.Graphics; public static float StringWidth(SpriteFont font, string text) { return font.MeasureString(text).X; } public static string WrapText(SpriteFont font, string text, float lineWidth) { const string space = " "; string[] words = text.Split(new string[] { space }, StringSplitOptions.None); float spaceWidth = StringWidth(font, space), spaceLeft = lineWidth, wordWidth; StringBuilder result = new StringBuilder(); foreach (string word in words) { wordWidth = StringWidth(font, word); if (wordWidth + spaceWidth > spaceLeft) { result.AppendLine(); spaceLeft = lineWidth - wordWidth; } else { spaceLeft -= (wordWidth + spaceWidth); } result.Append(word + space); } return result.ToString(); } 

谢谢! 我从as-cii的回答中采取了一些改变,在windows窗体中使用它。 使用TextRenderer.MeasureText而不是FormattedText

 static List<string> WrapText(string text, double pixels, Font font) { string[] originalLines = text.Split(new string[] { " " }, StringSplitOptions.None); List<string> wrappedLines = new List<string>(); StringBuilder actualLine = new StringBuilder(); double actualWidth = 0; foreach (var item in originalLines) { int w = TextRenderer.MeasureText(item + " ", font).Width; actualWidth += w; if (actualWidth > pixels) { wrappedLines.Add(actualLine.ToString()); actualLine.Clear(); actualWidth = w; } actualLine.Append(item + " "); } if(actualLine.Length > 0) wrappedLines.Add(actualLine.ToString()); return wrappedLines; } 

还有一点点说明: lineLine.Append(item +“”); 在检查宽度后需要放置,因为如果actualWidth>像素,这个字必须在下一行。

对于Winforms:

 List<string> WrapText(string text, int maxWidthInPixels, Font font) { string[] originalLines = text.Split(new string[] { " " }, StringSplitOptions.None); List<string> wrappedLines = new List<string>(); StringBuilder actualLine = new StringBuilder(); int actualWidth = 0; foreach (var item in originalLines) { Size szText = TextRenderer.MeasureText(item, font); actualLine.Append(item + " "); actualWidth += szText.Width; if (actualWidth > maxWidthInPixels) { wrappedLines.Add(actualLine.ToString()); actualLine.Clear(); actualWidth = 0; } } if (actualLine.Length > 0) wrappedLines.Add(actualLine.ToString()); return wrappedLines; } 

您可以使用MeasureString()方法从System.Drawing.Graphics类中获取string的(近似)宽度。 如果你需要一个非常精确的宽度,我想你必须使用MeasureCharacterRanges()方法。 下面是一些使用MeasureString()方法的示例代码,可以大致做出您所要求的内容:

 using System; using System.Collections.Generic; // for List<> using System.Drawing; // for Graphics and Font private List<string> GetWordwrapped(string original) { List<string> wordwrapped = new List<string>(); Graphics graphics = Graphics.FromHwnd(this.Handle); Font font = new Font("Arial", 10); string currentLine = string.Empty; for (int i = 0; i < original.Length; i++) { char currentChar = original[i]; currentLine += currentChar; if (graphics.MeasureString(currentLine, font).Width > 120) { // exceeded length, back up to last space int moveback = 0; while (currentChar != ' ') { moveback++; i--; currentChar = original[i]; } string lineToAdd = currentLine.Substring(0, currentLine.Length - moveback); wordwrapped.Add(lineToAdd); currentLine = string.Empty; } } return wordwrapped; } 
 public static string GetTextWithNewLines(string value = "", int charactersToWrapAt = 35, int maxLength = 250) { if (string.IsNullOrWhiteSpace(value)) return ""; value = value.Replace(" ", " "); var words = value.Split(' '); var sb = new StringBuilder(); var currString = new StringBuilder(); foreach (var word in words) { if (currString.Length + word.Length + 1 < charactersToWrapAt) // The + 1 accounts for spaces { sb.AppendFormat(" {0}", word); currString.AppendFormat(" {0}", word); } else { currString.Clear(); sb.AppendFormat("{0}{1}", Environment.NewLine, word); currString.AppendFormat(" {0}", word); } } if (sb.Length > maxLength) { return sb.ToString().Substring(0, maxLength) + " ..."; } return sb.ToString().TrimStart().TrimEnd(); } 

我想要包装文字,然后在我的图像中绘制。 我尝试了@ as-cii的答案,但在我的情况下并没有像预期的那样工作。 它总是扩展我的行的给定的宽度(也许是因为我用它与一个graphics对象来绘制我的图像中的文本)。 此外,他的答案(和相关的)只适用于> .Net 4框架。 在.net 3.5的框架中,没有函数Clear()用于StringBuilder对象。 所以这里是一个编辑版本:

  public static List<string> WrapText(string text, double pixels, string fontFamily, float emSize) { string[] originalWords = text.Split(new string[] { " " }, StringSplitOptions.None); List<string> wrappedLines = new List<string>(); StringBuilder actualLine = new StringBuilder(); double actualWidth = 0; foreach (string word in originalWords) { string wordWithSpace = word + " "; FormattedText formattedWord = new FormattedText(wordWithSpace, CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(fontFamily), emSize, System.Windows.Media.Brushes.Black); actualLine.Append(wordWithSpace); actualWidth += formattedWord.Width; if (actualWidth > pixels) { actualLine.Remove(actualLine.Length - wordWithSpace.Length, wordWithSpace.Length); wrappedLines.Add(actualLine.ToString()); actualLine = new StringBuilder(); actualLine.Append(wordWithSpace); actualWidth = 0; actualWidth += formattedWord.Width; } } if (actualLine.Length > 0) wrappedLines.Add(actualLine.ToString()); return wrappedLines; } 

因为我正在使用一个graphics对象,我试过@Thorins解决scheme。 这对我来说好多了,因为它包装了我的文本。 但是我做了一些改变,以便你可以给方法所需的参数。 还有一个错误:最后一行没有被添加到列表中,当for循环中的if-block的条件没有达到时。 所以你必须在这之后添加这条线。 编辑的代码如下所示:

  public static List<string> WrapTextWithGraphics(Graphics g, string original, int width, Font font) { List<string> wrappedLines = new List<string>(); string currentLine = string.Empty; for (int i = 0; i < original.Length; i++) { char currentChar = original[i]; currentLine += currentChar; if (g.MeasureString(currentLine, font).Width > width) { // exceeded length, back up to last space int moveback = 0; while (currentChar != ' ') { moveback++; i--; currentChar = original[i]; } string lineToAdd = currentLine.Substring(0, currentLine.Length - moveback); wrappedLines.Add(lineToAdd); currentLine = string.Empty; } } if (currentLine.Length > 0) wrappedLines.Add(currentLine); return wrappedLines; } 
Interesting Posts