Introduction
I was looking for code that can customise printing of .NET businessinfo
objects from my .NET application. A businessinfo
object might be an order
object which contains customer name, delivery address which I wanted to print as header on each page. The order will also have properties which are collections that have to be printed after the header on each page. This code gives us the flexibility to determine exactly what went on each printed page.
Background
I have used the GDI+ Architect to lay down the properties of the businessinfo
object in the print document class where I want them to be. It's a very useful tool in designing your print document class.
Using the Code
First we need to place the properties of the businessinfo
object in the PrintDocument
class using the GDI+ Architect tool. The key to the solution is laying down the items of the collection(DataTable
) in pages properly so that they don't overlap and all of the items from the collection are printed correctly.To do this, we need to calculate how many items can be printed on each page in the space left after printing the header and also considering different page sizes and margins.
The WriteHeader()
writes the header on top of each page and the WriteLineItem()
writes the line items from the collection.
The _PrintGraphics()
method first draws the header on each page and then draws the line items of the collection depending on how much space is left on the page.
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
txtDocumentPageNumberText = "Page " + currentPage + " of " + totalPages;
if ((this.currentPage == 1))
{
SpaceRemaningFirstPage =
WriteHeader(ref g, ref CurrentY, SpaceRemaningFirstPage);
}
if (dt.Rows.Count > 0)
{
for (int i = currentCount; i < dt.Rows.Count; i++)
{
if (SpaceRemaningFirstPage >= HeightRequiredByEachRowDt)
{
if (currentPage == 1)
{
SpaceRemaningFirstPage = WriteLineItem(ref g, ref CurrentY,
dt.Rows[i].ItemArray, SpaceRemaningFirstPage);
currentCount++;
}
}
else
{
if (SpaceRemainingInPage >= HeightRequiredByEachRowDt)
{
if (currentPage == CurrentPrintPage)
{
if (StartNewPage == true)
{
StartNewPage = false;
CurrentY = 0;
SpaceRemainingInPage = WriteHeader(ref g,
ref CurrentY, SpaceRemainingInPage);
}
SpaceRemainingInPage = WriteLineItem(ref g, ref CurrentY,
dt.Rows[i].ItemArray, SpaceRemainingInPage);
currentCount++;
}
}
}
}
}
}
The PageCreate()
adds the header data and the data for the DataTable
from the businessinfo
object.The printer name and the margin information are also set inside this method.
this.PrinterSettings.PrinterName = printerName;
bottomMargin = this.DefaultPageSettings.Margins.Bottom;
topMargin = this.DefaultPageSettings.Margins.Top;
paperHeight = this.DefaultPageSettings.PaperSize.Height;
The PagePrint()
method is called by the PrintPageEventHandler
when the PrintPage
event is called on the PrintDocument
class.
{
System.Drawing.Graphics g = e.Graphics;
this._PrintGraphics(g, e);
if ((this.currentPage < totalPages))
{
e.HasMorePages = true;
this.currentPage = (this.currentPage + 1);
}
else
{
e.HasMorePages = false;
}
CurrentPrintPage = currentPage;
SpaceRemainingInPage = paperHeight - bottomMargin;
StartNewPage = true;
}