Word wrap a string in multiple lines

2019-01-03 06:49发布

I am trying to word wrap a string into multiple lines. Every line will have defined width.

For example I would get this result if I word wrap it to an area of 120 pixels in width.

Lorem ipsum dolor sit amet,
consectetur adipiscing elit. Sed augue
velit, tempor non vulputate sit amet,
dictum vitae lacus. In vitae ante
justo, ut accumsan sem. Donec
pulvinar, nisi nec sagittis consequat,
sem orci luctus velit, sed elementum
ligula ante nec neque. Pellentesque
habitant 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. Proin in
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. Nulla
fermentum ornare rhoncus. Nulla
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
accumsan purus. Proin quis enim nec
sem tempor vestibulum ac vitae augue.

8条回答
我命由我不由天
2楼-- · 2019-01-03 07:35

For 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;
}
查看更多
放荡不羁爱自由
3楼-- · 2019-01-03 07:37

I'm wanted to wrap text to draw it afterwards in my image. I tried the answer from @as-cii, but it didn't work in my case as expected. It always extends the given width of my line (maybe because I use it in combination with a Graphics object to draw the text in my image). Furthermore his answer (and related ones) just work for >.Net 4 frameworks. In framework .Net 3.5 there is no function Clear() for StringBuilder objects. So here is an edited version:

    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;
    }

Because I'm working with a Graphics object I tried @Thorins solution. This worked for me much better, as it wraps my text right. But I made some changes so that you can give the method the required parameters. Also there was a bug: the last line was not added to the list, when the condition of the if-block in the for-loop was not reached. So you have to add this line afterwards. The edited Code looks like:

    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;
    }
查看更多
登录 后发表回答