Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining the number of lines in a text string?

Tags:

c#

drawstring

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!

like image 979
sooprise Avatar asked Feb 16 '11 17:02

sooprise


4 Answers

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);
like image 99
Alexander Avatar answered Sep 22 '22 19:09

Alexander


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;
}
like image 20
Holystream Avatar answered Sep 19 '22 19:09

Holystream


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.)

like image 30
2i3r Avatar answered Sep 21 '22 19:09

2i3r


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!

like image 39
Jonathan Avatar answered Sep 22 '22 19:09

Jonathan