Printing a WinForm as a Graphic

G

Guest

I'm using Visual Studio 2005 and C#. I need to print a WinForm used for data
entry as a graphic. In other words, I need to print the exact WinForm the
user sees on the screen.

I searched through the newsgroups, and found the code below. This seems
reasonable, except for the fact that the author does not provide his
SetSeq_Library. This is needed to load the Bitmap variable _ActiveFormImage.

Any suggestions on how to capture a WinForm as a Bitmap to feed to a
PrintPageEventHandler?

I like this solution much better than using GDI+, which was required in
Visual Studio 2003.

Thanks,
--
Randy


protected void PrintActiveForm(object sender, EventArgs e)
{
ToolStripMenuItem MenuItem=(ToolStripMenuItem)sender;
//MessageBox.Show(MenuItem.Name);
PrintDialog PD = new PrintDialog();
PrinterSettings PS = new PrinterSettings();
PrintDocument PrtDoc = new PrintDocument();

_ActiveFormImage = SetSeg_Library.SetCapture.Form(this);

PrtDoc.PrintPage += new PrintPageEventHandler(PrtDoc_PrintPage);
PD.Document = PrtDoc;
PD.ShowDialog();
PrtDoc.Print();

}

void PrtDoc_PrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawImage(this._ActiveFormImage, 0, 0);
}
 
K

Kevin Spencer

Hi Randy,

Use the base Control method "DrawToBitmap" method.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Chicken Salad Alchemist

Big thicks are made up of lots of little thins.
 
S

Stoitcho Goutsev \(100\)

randy,

Why don't you just use DrawToBitmap method?
Just keep in mind that depending on the controls that you have on the form
you may or may not get the exact snapshot. Some controls cannot be drawn on
a bit map e.g. RichTextBox.
 
G

Guest

The code below is what I came up with. Unfortunately, the contents of the
controls are blank. For instance, I have TextBox with some text. I see the
text on the screen, but the TextBox is empty when it prints using this code.
--
Randy


private Bitmap _ActiveFormImage;
private void printToolStripMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem MenuItem = (ToolStripMenuItem)sender;
//MessageBox.Show(MenuItem.Name);
PrintDialog PD = new PrintDialog();
PrinterSettings PS = new PrinterSettings();
PrintDocument PrtDoc = new PrintDocument();

Rectangle r = new Rectangle(0, 0, this.Width, this.Height);
this.DrawToBitmap(_ActiveFormImage, r);

PrtDoc.PrintPage += new PrintPageEventHandler(printDocument1_PrintPage);
PD.Document = PrtDoc;
PD.ShowDialog();
PrtDoc.Print();
}

private void printPrevewToolStripMenuItem_Click(object sender,
EventArgs e)
{
printPreviewDialog1.ShowDialog();
}
 
K

Kevin Spencer

You have a few things wrong here.

First, you never instantiate _ActiveFormImage. The DrawToBitmap method draws
on a Bitmap, not on null.

Second, you didn't post the crucial code, which does the actual printing.
That would be the event handler for the PrintDocument.PrintPage event. This
event passes a PrintPageEventArgs instance, which contains, among other
things, the Graphics device you need to draw on.

Third, you're not checking the available space to print on.

Fourth, you're printing, even if the user hits the Cancel button.

The process goes like this:
The PrintDocument contains all the information needed to print, including
things like the PageSettings, which contains the page orientation, margins,
etc., and the PrinterSettings, which is used to determine which printer to
use and what settings to give it. The PrinterSettings isn't nearly as
important as the PageSettings, because the PageSettings determines the
height and width of the page, the printable area of the page, the margins,
etc.

The PrintDialog class, like any other dialog, returns a DialogResult when it
is closed by either the OK or Cancle button. The value of this DialogResult
is used to determine whether to go forward or not.

When you call the Print method of the PrinterDocument, it fires the
PrintPage event, which passes a PrintPageEventArgs instance containing the
relevant data to print with. This includes the available area to print in,
which is specified by the PrintDocument's PageSettings property. You draw
with the Graphics object in the same way you would draw to any Graphics
object.

So, what you need to do is to remove the PrintDocument from the method it is
now encapsulated in, and make it into a field or property of the class, so
that you can (1) Make configuration changes if desired, to the print
configuration, and (2) measure the available space in the page, for the
purpose of making sure that your form is fully inside the page, and for
aligning it within the page.

I would wait to draw the Bitmap in the PrintPage event handler as a good
practice. This will ensure that the latest state of the form is printed,
regardless of any future changes you make to the code. In the event handler
for the PrintPage event, get the Bounds of the form, and instantiate your
Bitmap to that size. Take note of the height and width, as you may want to
change the orientation of the printing if, for example (as with most Forms)
the width is greater than the height, in which case you would probably want
to use Landscape orientation.

Once you have your Bitmap instantiated, call the DrawToBitmap method to draw
the Form on the Bitmap. Then get the Graphics from the PrintPageEventArgs
instance, and draw the Bitmap to the Graphics.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Chicken Salad Alchemist

Big thicks are made up of lots of little thins.
 
J

Jeffrey Tan[MSFT]

Hi Randy,

Thanks for your feedback!

To draw image while printing or in print preview dialog, you should handle
the print document's PrintPage event, and draw to the Graphic object of
PrintPageEventArgs.

The code snippet below works well on my side:

private void button1_Click(object sender, EventArgs e)
{
PrintPreviewDialog ppd = new PrintPreviewDialog();
ppd.Document = new PrintDocument();
ppd.Document.PrintPage += new PrintPageEventHandler(Document_PrintPage);
ppd.ShowDialog();
}

void Document_PrintPage(object sender, PrintPageEventArgs e)
{
Bitmap bt = new Bitmap(this.dataGridView1.Width,
this.dataGridView1.Height);
this.dataGridView1.DrawToBitmap(bt, new Rectangle(0, 0,
this.dataGridView1.Width, this.dataGridView1.Height));
e.Graphics.DrawImage(bt, new Point(0, 0));
}
Note: I used a already databinding DataGridView control on the form as
printing source, while use a PrintPreviewDialog to show the print result at
runtime. You may give this code sinppet a test on your side. If you need my
sample project please feel free to tell me.

Finally, if you are curious, DrawToBitmap is a .Net2.0 new method, which
encapsulates WM_PRINT Win32 message and BitBlt Win32 API to do the printing
work.

Hope this helps!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top