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
Feel free to download the class and demo application: ControlPrintPageEventHandler.zip.