Word wrap a string in multiple lines
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;
}
Add WindowsBase
and PresentationCore
libraries.
Here's a version I came up with for my XNA game...
(Note that it's a snippet, not a proper class definition. Enjoy!)
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();
}
Thanks! I take a method from as-cii's answer with some changes, for using it in Windows Forms. I am using TextRenderer.MeasureText instead of 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;
}
And a little remark: the line actualLine.Append(item + " "); needs to be placed after checking the width, because if actualWidth > pixels, this word must be in the next line.