Tim Van Wassenhove

Passionate geek, interested in Technology. Proud father of two

31 Dec 2006

Print a Control

A while ago i discovered the DrawToBitmap method on the Control class. The availability of this method makes it relatively easy to implement a PrintPageEventHandler for the PrintDocument class. Here is an example implementation that prints a DataGridView

private void buttonPrint_Click(object sender, EventArgs e)
{
	this.printDocument1.Print();
}

void printDocument1_BeginPrint(object sender, PrintEventArgs e)
{
	this.currentPage = 0;
}

private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
	Size oldSize = this.dataGridView1.Size;
	this.dataGridView1.Height = Math.Max(this.dataGridView1.Height, this.dataGridView1.PreferredSize.Height);
	this.dataGridView1.Width = Math.Max(this.dataGridView1.Width, this.dataGridView1.PreferredSize.Width);

	int requiredPagesForWidth = ((int)this.dataGridView1.Width / e.MarginBounds.Width) + 1;
	int requiredPagesForHeight = ((int)this.dataGridView1.Height / e.MarginBounds.Height) + 1;
	int requiredPages = requiredPagesForWidth * requiredPagesForHeight;
	e.HasMorePages = (this.currentPage < requiredPages - 1); 
	int posX = ((int)this.currentPage % requiredPagesForWidth) \* e.MarginBounds.Width; 
	int posY = ((int)this.currentPage / requiredPagesForWidth) \* e.MarginBounds.Height; 
	Graphics graphics = e.Graphics; 
	Bitmap bitmap = new Bitmap(this.dataGridView1.Width, this.dataGridView1.Height); 
	this.dataGridView1.DrawToBitmap(bitmap, this.dataGridView1.Bounds); 
	graphics.DrawImage(bitmap, new Rectangle(e.MarginBounds.X, e.MarginBounds.Y, e.MarginBounds.Width, e.MarginBounds.Height), new Rectangle(posX, posY, e.MarginBounds.Width, e.MarginBounds.Height), GraphicsUnit.Pixel); 
	this.dataGridView1.Size = oldSize; 
	++this.currentPage; 
}

Now that you understand the main idea, let’s wrap it in a class and make it reusable: ResizedControlPrintPageEventHandler. Using this class is as simple as

// Initialise a controlPrintPageEventHandler and register the PrintPage method...
ResizedControlPrintPageEventHandler resizedControlPrintPageEventHandler = new ResizedControlPrintPageEventHandler(this.dataGridView1);
this.printDocument1.PrintPage += resizedControlPrintPageEventHandler.PrintPage;

// Print the control
private void buttonPrint_Click(object sender, EventArgs e)
{
	this.printDocument1.Print();
}

// Give the user a preview
private void buttonPreview_Click(object sender, EventArgs e)
{
	this.printPreviewDialog1.Show();
}

Here are a couple of screenshots

Screenshot of demo application that has a datagridview with scrollbars.

Screenshot of print preview. Notice that the scrollbars are gone.

Screenshot of the print document.

Feel free to download the class and demo application: ControlPrintPageEventHandler.zip.