我正在尝试将字符串换成多行。每一行都有定义的宽度。
例如,如果我将其包装到宽度为120像素的区域,我会得到这个结果。
Lorem ipsum dolor sit amet,
奉献精神。 Sed augue
velit,tempor non vulputate sit amet,
简历lacus。简历ante
justo,ut accumsan sem。 Donec
pulvinar,nisi nec sagittis consequat,
sem orci luctus velit,sed elementum
ligula ante nec neque。 Pellentesque
居民morbi tristique senectus et netus et malesuada fames ac turpis
egestas。 Etiam erat est,pellentesque
eget tincidunt ut,egestas in ante。
Nulla vitae vulputate velit。进入中 congue neque。 Cras rutrum 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。法无
发酵ornare rhoncus。法无
gravida vestibulum odio,vel commodo
magna condimentum quis。 Quisque
sollicitudin blandit mi,non varius
libero lobortis eu。 Vestibulum eu
turpis massa,id tincidunt orci。
Curabitur pellentesque urna non risus
adipiscing facilisis。 Mauris vel
累积purus。 Proin quis enim nec
sem tempor vestibulum ac vitae augue。
答案 0 :(得分:38)
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;
}
添加WindowsBase
和PresentationCore
个库。
答案 1 :(得分:20)
以下代码取自blogpost,有助于完成工作。
你可以这样使用它:
string wordWrappedText = WordWrap( <yourtext>, 120 );
请注意,代码不是我的,我只是在这里报告您商品的主要功能。
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;
}
答案 2 :(得分:5)
这是我为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();
}
答案 3 :(得分:3)
谢谢!我从 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;
}
还有一点评论: actualLine.Append(item +&#34;&#34;); 这一行需要在检查宽度后放置,因为if actualWidth&gt;像素,这个词必须在下一行。
答案 4 :(得分:1)
对于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;
}
答案 5 :(得分:0)
您可以使用MeasureString()方法从System.Drawing.Graphics类中获取字符串的(近似)宽度。如果你需要一个非常精确的宽度,我认为你必须使用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;
}
答案 6 :(得分:0)
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();
}
答案 7 :(得分:0)
我想要在我的图片中包装文字以后绘制它。我尝试了@ as-cii的答案,但它没有像我预期的那样在我的情况下工作。它总是扩展我的行的给定宽度(可能是因为我将它与Graphics对象结合使用以在我的图像中绘制文本)。此外,他的答案(以及相关的答案)仅适用于&gt; .Net 4框架。在框架.Net 3.5中, StringBuilder 对象没有函数 Clear()。所以这是一个经过编辑的版本:
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解决方案。这对我来说更好,因为它包含了我的文本。但我做了一些更改,以便您可以为方法提供所需的参数。还有一个错误:当没有达到for循环中if块的条件时,最后一行没有添加到列表中。所以你必须在之后添加这一行。编辑后的代码如下:
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;
}