Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Windows form screenshot and print preview in VB.NET

0.00/5 (No votes)
12 Mar 2012 1  
How to take a screenshot of a Windows form and then print it.

This article talks about how to take a screenshot of a Windows form and then print it.

As I am working on an application, I end up with several smaller test application to learn about different ways to do something. After creating them they are a great source to go back to if I don’t have to do a certain thing for a while so I can remember how to do it. Always comment code well.

In my current main project, it inputs 4 dimensions and 2 options , does over 100 calculations and then outputs 8 final dimensions.

I was wanting to print the form and output for the end user, and since I’ve haven’t worked much with printing, or screenshots I had a lot to learn.

I wasn’t sure how to print a form so I added all of the standard controls and looked to see what it would do for me. That didn’t turn out very well, you can’t just add the controls and hope to fumble your way thru to get it to work. So I downloaded and installed the Visual Basic Power pack 3. After some reading, trial, and allot of error I decided I didn’t want to use the Power pack because it had to be installed on the end user system in order for the printing to work. So I went back to the internet , and started by searching for how to take a screenshot. I found an interesting C# version that took a screenshot of the entire screen then saved it to a file (located here). After converting it to VB.NET, I was ready to see what it could do.

It worked great for taking a screen of the entire screen but I wanted just the the form.

C# and converted VB.NET code:

//C#
private void btnCapture_Click(object sender, EventArgs e)
{
    Graphics graph = null;
    try
    {
        Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, 
                                Screen.PrimaryScreen.Bounds.Height);
        graph = Graphics.FromImage(bmp);
        graph.CopyFromScreen(0,0, 0, 0, bmp.Size);
        SaveImage(bmp);
    }
    finally
    {
'VB.NET

Private Sub btnCapture_Click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles btnCapture.Click
    Dim graph As Graphics = Nothing
    Try
        Dim bmp As New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
        graph = Graphics.FromImage(bmp)
        graph.CopyFromScreen(0,0, 0, 0, bmp.Size
        SaveImage(bmp)
    Catch ex As Exception
    End Try
End Sub

(Note: The C# code errored out when trying to use a online code converter.)

Now that I had working code to create the screenshot with, it was time to start tweaking the code to get it to just take a screenshot of just the form.

Rather than taking the screenshot then finding and opening up the image each time I saved the file, I added the ability for MS Paint to open and view the image after each screenshot was taken, it will overwrite the file each time so only 1 file is left, unless you add code to delete the file. After the screenshot was saved I could go back and change the numbers for the the size, and location of what was captured. After Getting the result you want you can just comment out the code or remove it all together.

(Note 2: The screenshot is saved to the debug or release folder that the program is run from, using the code above “SaveImage(bmp)”. I had to change the output to the “c:\Filename.png” because it would not find the file with the number of characters it took for the path length to where the projects were saved, and starting MS Paint from code to to open the file.)

ScreenCaptureSavedandOpenedInPaint

Final code for screen capture test:

Private Sub GetScreenshot_Click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles GetScreenshot.Click
    Dim graph As Graphics = Nothing Try
    ' gets the upper left hand coordinate of the form
    Dim frmleft As System.Drawing.Point = Me.Bounds.Location

    'use the commented out version for the full screen
    'Dim bmp As New Bitmap(Screen.PrimaryScreen.Bounds.Width, _Screen.PrimaryScreen.Bounds.Height)
    'this version get the size of the form1
    'The + 8 adds a little to right and bottom of what is captured.
    Dim bmp As New Bitmap(Me.Bounds.Width + 8, Me.Bounds.Height + 8)

    'creates the grapgic
    graph = Graphics.FromImage(bmp)

    'Gets the x,y coordinates from the upper left start point
    'used below Dim screenx As Integer = frmleft.X
    Dim screeny As Integer = frmleft.Y

    ' The - 5 here allows more of the form to be shown for the top and left sides.
    graph.CopyFromScreen(screenx - 5, screeny - 5, 0, 0, bmp.Size)

    ' Save the Screenshot to a file
    bmp.Save("C:\temp.png")

    'Open File and load in MS Paint Dim filepath As String
    filepath = "C:\temp.png"
    Process.Start("mspaint.exe ", filepath)

    bmp.Dispose()
    graph.Dispose()
Catch ex As Exception
    MsgBox(ex.Message)
End Try End Sub

The code above is just the button click event to get the capture and then start MS Paint with the saved screenshot.

As you can see from all of the comments we first set the variable graph = to nothing.

Next we want to get the location of the upper left hand corner of the form. We then set the variable bmp as a new Bitmap type and get the size of what we want to capture. I added 8 to the width and height to get more of the right and bottom of the border to display. It may be different for different border types.

We set the variable graph = to a graphics object created from the image bmp. Next we get the X,Y coordinates of the upper left hand corner of our form from the “frmleft” variable we got first.

We then do “graph.CopyFromScreen(screenx – 5, screeny – 5, 0, 0, bmp.Size)”. Here I subtracted 5 from each of the input X,Y coordinated to capture more of the left and top of the form.

This saves the image to the variable starting at the input X,Y and the output X,Y and then Width and height of the capture represented as the variable “bmp.Size” .The output X, Y coordinates will almost always be “0” Zero.

Next we save the file to the local system so MS Paint can open it for viewing the result. As of this writing I have not tested for ways of bypassing saving the file to disk yet. We then open the file for viewing with MS Paint. Finally we Dispose, or release the graphic objects.

The next trick is to figure out how to output this to a printer

After several hours and many failed attempts trying any code I could find, I finally discovered that text and images are handled a little differently.

Final code for outputting to a Print Preview control:

Private Sub btnPrintPreview_Click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles btnPrintPreview.Click

    PrintPreviewDialog1.ShowDialog()

End Sub

Public Sub New()
    MyBase.New()
    InitializeComponent()
End Sub

Private Sub Print_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load
    ' The example assumes your form has a Button control,
    ' a PrintDocument component named myDocument,
    ' and a PrintPreviewDialog control.
    ' Handle the PrintPage event to write the print logic.
    AddHandler PrintDocument2.PrintPage, AddressOf Me.printDocument2_PrintPage

    ' Specify a PrintDocument instance for the PrintPreviewDialog component.
     Me.PrintPreviewDialog1.Document = Me.PrintDocument2
End Sub

Private Sub printDocument2_PrintPage(ByVal sender As Object, _
            ByVal e As System.Drawing.Printing.PrintPageEventArgs)
    ' Specify what to print and how to print in this event handler.
    ' This gives us the left X, and the top Y location of the printable area
    ' plus how much we want something to pad to the right or from the top of the Printable Area
    'If the number was equal the the printable area it may not print. 
    Dim prnborderX As Single
    prnborderX = PrintDocument2.DefaultPageSettings.PrintableArea.X + 1 
    Dim prnborderY As Single
    prnborderY = PrintDocument2.DefaultPageSettings.PrintableArea.Y + 10
    'This is the Width and heigth of the printable area. As a Single. 
    Dim pagewidth As Single
    pagewidth = PrintDocument2.DefaultPageSettings.PrintableArea.Width
    Dim pageHeight As Single
    pageHeight = PrintDocument2.DefaultPageSettings.PrintableArea.Height

    'Set the font, text color,and line color Dim f As Font = New Font("Vanada", 12)
    Dim br As SolidBrush = New SolidBrush(Color.Black)
    Dim p As Pen = New Pen(Color.Black)
    Dim g As Pen = New Pen(Color.CornflowerBlue)

    ' Get the strings for the paper size and the printable area for the output. 

    Dim PrntDoc2 As String
    PrntDoc2 = "Paper Size = " & PrintDocument2.DefaultPageSettings.PaperSize.ToString
    Dim prndoc2default
    prndoc2default = "Printable Area = " & PrintDocument2.DefaultPageSettings.PrintableArea.ToString

    e.Graphics.DrawString(PrntDoc2, f, Brushes.RosyBrown, 50, 70)
    'paint the text for paper size
    e.Graphics.DrawString(prndoc2default, f, Brushes.Black, 50, 90)
    'paint the text printable area
    e.Graphics.DrawRectangle(p, 50, 150, 300, 150)
    'paint the small box
    'paint the border box  around the printable area
    e.Graphics.DrawRectangle(g, prnborderX, prnborderY, pagewidth - 50, pageHeight - 25)

    'paint the image to the printpreview control and scale to fit.
    Dim drawImg As New Bitmap("C:\temp.png")
    Dim mgHeight As Single = drawImg.Height
    Dim mgWidth As Single = drawImg.Width
    'This part is for the scaling , gets the input size and the output 
    'size for image to scale to automaticly
    Dim sourceRectangle As New Rectangle(0, 0, mgWidth, mgHeight)
    Dim destRetangle1 As New Rectangle(40, 350, pagewidth - 75, 600)
    e.Graphics.DrawImage(drawImg, destRetangle1, sourceRectangle, GraphicsUnit.Pixel)

    'get the image size and paint the text of the sizes
    'to the print preview control 
    Dim PictureSize As String
    PictureSize = ("Image Width = " & mgWidth.ToString & _
                   "   Image Height = " & mgHeight.ToString)
    e.Graphics.DrawString(PictureSize, f, Brushes.Blue, 50, 110)

End Sub

The first thing we need to do is add a standard Print Preview Control and a Print Document control to the form. Just using these you don’t need the power pack. (As far as I know of anyway.)

Next a Button or use a menu item for opening the Print Preview window with the click event.

Next we add a Component initializer for the code in the Print_Load sub.

Next we need the handlers for the Print Document Control and the “Address Of “ to the sub that will do the work of what will be “Painted” to the Print Preview control.

PrintDocument2 is the name of the Print Document control that was added they need to match. printDocument2_PrintPage is the name of the sub that will do the work.

If the Component initializer and the “Print_Load” sub are not present then the Print preview control will not display anything.

Next we move onto the printDocument2_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs). printDocument2_PrintPage is a variable name but the rest needs to be the same.

Next I need to understand the terms and what they are used for.

Font, the font to use , set what font name you want here. Just make sure it is common font or it may fail on other systems.

Solid Brush, solid brush will be used with text for setting the color, or filling in areas.

Pen, the pen is used for setting the color of lines or shapes.

e.Graphics.DrawString this is event driven, so this tells the DrawString event to draw the (string that is referenced, the font to use, the color of the brush to use, the X,Y coordinates to start painting the text at from the top left hand corner of the page).

This test program:

  1. Outputs an Outline Box just inside of the the printable area, to help see where the printable area is as laid out on the print preview control.
  2. Prints the paper size of the default printer as a string.
  3. Prints the Printable Area of the default printer, (this may be different for each individual printer).
  4. Draws a box (left over from some test code).
  5. Then paints the image scaled to the width of the printable area. I used the the printable area outline box to help me center the image by adjusting the parameters.

When this page was printed the outline box was centered on the paper, not offset to the left like the preview shows.

Lets see what the output looks like:

PrintPreviewTest12

At this point after all that I have learned, rather than outputting a screenshot to the print preview control, I can just pass the text needed to be displayed from either the output text boxes or globally declared variables for the items I need displayed, for a more printer friendly version.

Final Notes:

This test application does not have error handling for when the image file does not exist. So the screenshot button will need to be hit at least once.

This test program does not have any code for using the landscape view. But another sub form in this project has a button for opening the “print setup dialog” but no code for saving a selection of landscape or portrait.

On another sub form in this project is a button to list all of the default values for the default printer. All sub forms can be opened from a button starting from the main form.

Download:

The source and binary are available from my SkyDrive folder.

FormScreenshotPrint.zip

Do to Microsoft Closing down their offering of Microsoft Office Live Small Business service and forcing their current customers to either move to the new Office 365 program and completely rebuild their web sites again or find a new web host and rebuild there site. Effective April 30, 2012.

After that My website may be gone or moved to a new host. I also may not be able to keep the SkyDrive location the my articles refer to after that since it is tied to my website.

Conclusion

After all that I have learned over that last few days, once you learn what is required to do the job it is not difficult to implement the screen shot or the printing. I see no need at the moment to use a third party control that may require it to be installed, and possibly break you application because of it. Just some number changes can move your image or text anywhere you want. A person could even make a few snippets with the replacements set for quicker use later.

I hope someone learned as much from this adventure as I did.

Links

MSDN sites

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here