The other day a user asked me how to print out a form. I suggested they use my Form Capture article which catches the bitmap that the form is in by using bit belting commands from the old windows SDK. It turns out this is not the ideal solution because it involves old Windows SDK code. A better solution would be to draw the controls individually onto the printing graphics object. But how the heck do I print a control? Do I have to actually copy Microsoft Controls bit by bit? Do I have to mimic the shading and 3d features by drawing different lines that produce shading effects?
Figure 1 - A Form and the Print Preview of the same Form
It turns out that Microsoft provides the user with a helpful class that allows us to draw these elusive controls called ControlPaint. This class is more like an API containing a list of static methods to help you paint the controls. Below I listed the ones used in this article and their purpose:
| Method in ControlPaint | Description |
| DrawButton | Draws a Button in the Graphics area. Note this command will not draw any text or image on the button |
| DrawCheckBox | Draws a Checkbox in the Graphics area |
| DrawBorder3D | This will allow you to draw any 3D Border Side. |
Table 1 - Methods of ControlPaint used in this article
As we have discussed in previous printing articles on C# Corner, printing and drawing are accomplished almost the same way, by writing to a device context, or in the case of .NET, to a Graphics Object. We are not going to go into detail on how to set up the printing components for calling the method that paints the controls to the printer. Please refer to Printing in C# on the site to see how to set up the Print_Page event handler.
Our event handler for printing the form will call a method called, ironically, DrawForm, and perform all of the control painting here. Below is the method DrawForm in our Form class:
Listing 1 - Draw the Form and controls to the printer Graphics object
The code above cycles through each control in the form and paints the control to the Graphics object. The code takes advantage of the ControlPaint methods we mentioned above. The DrawButton method is used to paint both the 3D button controls and the 3D text boxes. The DrawCheckBox method of the ControlPaint class is used to draw the 3D checkbox. In every case we need to draw the text separately from the control using the DrawString method of the Graphics Object. We also needed to fill in the TextBox background with the FillRectangle method in the Graphics object.
- void DrawForm(Graphics g, int resX, int resY) {
- g.FillRectangle(new SolidBrush(this.BackColor), 0, 0, this.Width, this.Height);
- float scale = resX / ScreenResolution;
- // Cycle through each control on the form and paint it to the printe
- foreach(Control c in Controls) {
- // Get the time of the next control so we can unbox it
- string strType = c.GetType().ToString().Substring(c.GetType().ToString().LastIndexOf(".") + 1);
- switch (strType) {
- case "Button":
- Button b = (Button) c;
- // Use the ControlPaint method DrawButton in order to draw the button of the form
- ControlPaint.DrawButton(g, ((Button) c).Left, ((Button) c).Top, ((Button) c).Width, ((Button) c).Height, ButtonState.Normal);
- // We also need to draw the text
- g.DrawString(b.Text, b.Font, new SolidBrush(b.ForeColor), b.Left + b.Width / 2 - g.MeasureString(b.Text,
- b.Font).Width / 2, b.Top + b.Height / 2 - g.MeasureString("a", b.Font).Height / 2, new StringFormat());
- break;
- case "TextBox":
- TextBox t = (TextBox) c;
- // Draw a text box by drawing a pushed in button and filling the rectangle with the background color and the text
- // of the TextBox control
- // First the sunken border
- ControlPaint.DrawButton(g, t.Left, t.Top, t.Width, t.Height, ButtonState.Pushed);
- // Then fill it with the background of the textbox
- g.FillRectangle(new SolidBrush(t.BackColor), t.Left + 1, t.Top + 1, t.Width + 2, t.Height - 2);
- // Finally draw the string inside
- g.DrawString(t.Text, t.Font, new SolidBrush(t.ForeColor), t.Left + 2, t.Top + t.Height / 2 - g.MeasureString("a", t.Font).Height / 2, new StringFormat());
- break;
- case "CheckBox": // We have a checkbox to paint, unbox it
- CheckBox cb = (CheckBox) c;
- // Use the DrawCheckBox command to draw a checkbox and pass the button state to paint it checked or unchecked
- if (cb.Checked)
- ControlPaint.DrawCheckBox(g, cb.Left, cb.Top, cb.Height / 2, cb.Height / 2, ButtonState.Checked);
- else
- ControlPaint.DrawCheckBox(g, cb.Left, cb.Top, cb.Height / 2, cb.Height / 2, ButtonState.Normal);
- // Don't forget the checkbox text
- g.DrawString(cb.Text, cb.Font, new SolidBrush(cb.ForeColor), cb.Right - cb.Height - g.MeasureString(cb.Text, cb.Font).Width, cb.Top, new StringFormat());
- break;
- }
- }
- }
Conclusion
Much more code can be added to this project to handle radio buttons, listviews, listboxes, and comboboxes. The ControlPaint class contains methods that can help you to paint other Window Form controls such as DrawScrollButton, DrawRadioButton, DrawGrid, DrawComboButton and DrawFocusRectangle. If your form only contains edit boxes, checkboxes, and buttons, then this code may cover the bulk of your work.

Mukhtiyar AliPosted Aug 17, 2017, 1:13 AM
Dear sir how preview or print richtextbox image file or maths equation text.
khokon sarkerPosted Mar 28, 2013, 5:35 AM
thank you and grateful to you for giving a nice solution
ria pasaribuPosted Jun 14, 2012, 5:02 AM
How if i want to print datagridview in my form? can i get the clas to draw a datagrid. Thanks
ria pasaribuPosted Jun 14, 2012, 5:02 AM
How if i want to print datagridview in my form? can i get the clas to draw a datagrid. Thanks
mohammad jamaliPosted Mar 14, 2011, 10:07 AM
hi. i have two line text in a richtextbox on my form but when i used this code print it in one line.
mohammad jamalieditedPosted Mar 5, 2011, 1:27 PMEdited Apr 17, 2011, 7:13 AM
1
mohammad jamalieditedPosted Feb 28, 2011, 1:25 PMEdited Apr 17, 2011, 7:12 AM
this code help me very much. i am mohammad .
KouroshPosted Dec 25, 2010, 8:33 AM
Thanks for your very good Article
Steffan HoekePosted Aug 17, 2010, 9:21 AM
Any chance this can be updated to also accomodate User Controls and GroupBoxes (which in turn contain controls) ?
Dario CortesPosted Aug 5, 2010, 4:59 PM
Muchas Gracias por tu codigo me sera de mucha ayuda
Nishant NairPosted May 20, 2009, 2:10 AM
Thank you for this code. i have a doubt, how to print datagridview and radiobutton by this method. pls help me out
DamoneditedPosted Jan 22, 2008, 10:28 AMEdited Jan 22, 2008, 1:47 PM
How would you print things like textboxes out if they were inside a label?
NigelPosted Apr 26, 2007, 2:05 AM
Please supply info on resX, resY and the value of ScreenResolution.
ahmad daneshmandPosted Feb 15, 2007, 10:32 AM
I wrote some class for my data and store them in some random or seq files . I see some controls in microsoft visual stdio 2005 for printing like ( PrintDocument) but I dont know how to use them. I need for your help very much. thanks