Determining the number of lines in a text string?

9.1k views Asked by At

As part of a printing class, I want to be able to print long strings over multiple pages, but I don't know how to calculate the height of the entire string, which I will determine by first counting the number of lines in my string. I know I can count the number of line breaks, but I am also using word-wrap, so line breaks will be added whenever a line goes on past the width of the page. So I suppose I could count the number of line breaks, and figure out the width of each line, and figure out if there is a need for a word-wrap line break for each line, but this seems like an overly complicated problem for something I imagine can be done more simply.

e.Graphics.DrawString(multiPageString, new Font("Courier New", 12), Brushes.Black, new RectangleF(0, 0, 810, pageHeight));

If you have any advice, please let me know thanks!

6

There are 6 answers

0
Jonathan On BEST ANSWER

I agree with @David Heffernan provide a really bog standard implementation. Its way to complicated for the value they are going to achieve, or go with something that will produce 100% reliable printing results etc Reporting Services. I feel your pain, printing is painstaking!

2
David Heffernan On

Why don't you just stuff it into a rich text control and print that? No more than 10-15 lines of code should get it done.

2
Oleg Rudckivsky On

If you want to measure size of the string use method Graphics.MeasureString(string, Font)

graphics.MeasureString("some string", new Font("Arial", 10))
2
Holystream On

This can be edited, but you can probably use this as starting location?

const int PAGE_MAX_CHARS_PER_LINE = 30;
var message = "this is a really long line and it will make your eyes pop out but I don't know how to present a long line differently.  So you will have to stick with\r\nit.   I think the above line should be long enough\r\n\r\n I would love to see how this turns out.";
var lines = message.Split(new string [] {"\r\n"}, StringSplitOptions.None);
var linesCount = lines.Length;

var longLines = lines.Where(i=>i.Length > PAGE_MAX_CHARS_PER_LINE);
foreach(var l in longLines)
{
  int numberOfLines = (int)Math.Ceiling((double)l.Length / PAGE_MAX_CHARS_PER_LINE); /// Will need to embed graphics measurement mechanism here?
  linesCount += numberOfLines - 1;
}
2
Alexander On
int iMaxWidth = 240; // Maximum width, in pixels
string sText = @"blah-blah-blah";
Font objFont = new Font("Times New Roman", 13, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point);
StringFormat sfFmt = new StringFormat(StringFormatFlags.LineLimit);
Graphics g = Graphics.FromImage(new Bitmap(1, 1));
int iHeight = (int)g.MeasureString(sText, objFont, iMaxWidth, sfFmt).Height;
int iOneLineHeight = (int)g.MeasureString("Z", objFont, iMaxWidth, sfFmt).Height;
int iNumLines = (int)(iHeight/iOneLineHeight);
0
2i3r On

As @Alexander suggested, one good and pretty simple approach would be just to test it without drawing. let the Graphics do the test for you.

Suppose you have maximum line length of wrapWidth in pixel, and the string you want to check is multiPageString, then you may use this function:

private int GetNumOfLines(string multiPageString, int wrapWidth, Font fnt)
{
    StringFormat sfFmt = new StringFormat(StringFormatFlags.LineLimit);
    using(Graphics g = Graphics.FromImage(new Bitmap(1, 1)))
    {
        int iHeight = (int)g.MeasureString(multiPageString, fnt, wrapWidth, sfFmt).Height;
        int iOneLineHeight = (int)g.MeasureString("Z", fnt, wrapWidth, sfFmt).Height;
        return (int)(iHeight/iOneLineHeight);
    }
}

(This function is derived from @Alexander answer.)