Introduction
At least once, in the life of a programmer, it succeeds that the moment arrives to print a text document. The task is quite simple for a .NET programmer, but even more with PrintTextDocument
class. This class was written to help in printing text documents, adding customizable header and footer and line numbers to the printed text. The text can be printed wrapping the exceeding text to the next line, truncating it, or spanning it through many pages. The last mode is useful when printing text banners like the ones coming from ASCII Art or from text tables with many columns. PrintTextDocumen
is derived from System.Drawing.Printing.PrintDocument
and provides some extra properties that set the class behavior during printing.
Using the code
The class is very simple to use. Typically, you create an instance of the PrintTextDocument
class, set the properties that describe how to print, for example, header and footer, and call the Print
method to start the printing process; just like you do with the PrintDocument
class. The class constructor is: PrintTextDocument(string filepath)
, where filepath
is the full path of the text document to print.
PrintTextDocument toPrint = new PrintTextDocument(filename);
toPrint.PrintMode = PrintTextMode.WrapText;
toPrint.PrintLineNumbers = true;
toPrint.Print();
Points of interest
When I wrote the code, the first version was quite simple. The OnPrintPage
override was made of a loop that scanned through the text file and called the MeasureString
and DrawText
methods. After some trials, I noticed that there was a bug in the text wrapping. It was as if MeasureString
did not take care of the spaces at the end of the line. This was because of the way I wrote the GetLineBreakCharPosition
function. This function checks the result of MeasureString
and makes the adjustment according to the number of spaces that came at the end of the measured text. I don’t know if this is a bug of MeasureString
. I did not find any useful information regarding this strange behavior. I even tried to use StringFormat
with the MeasureString
method but it did not get better. I’d like to know if there is another way to do what GetLineBreakCharPosition
does.
private int GetLineBreakCharPosition(Graphics gfx,
string text, RectangleF rectangle)
{
StringFormat fmt =
new StringFormat(StringFormatFlags.MeasureTrailingSpaces);
int charactersOnLine = 0;
int lines = 0;
SizeF sizeText = gfx.MeasureString(text, _printFont,
rectangle.Size, fmt,
out charactersOnLine, out lines);
string rem = text.Substring(0, charactersOnLine);
if(rem.EndsWith(" ") && (charactersOnLine < text.Length))
{
string noSpaces = rem.TrimEnd(new Char[] { ' ' });
int nSpaces = rem.Length - noSpaces.Length;
SizeF sizeChunk = gfx.MeasureString(noSpaces,
_printFont,
rectangle.Size, fmt,
out charactersOnLine, out lines);
string spacer = String.Empty;
while(sizeChunk.Width <= rectangle.Width)
{
spacer += " ";
sizeChunk = gfx.MeasureString(noSpaces + spacer,
_printFont,
new PointF(0, 0), fmt);
}
charactersOnLine += spacer.Length -
((sizeChunk.Width > rectangle.Width) ? 1 : 0);
}
return charactersOnLine;
}
History
- 28/05/2006 - v.1.0.0.0 -
PrintTextDocument
simple text file print class with custom header, footer, and printing mode.