Windows form screenshot and print preview in VB.Net

How to take a screen shot 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 screen shot 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.

Next we 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.

Next 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.

Next “ 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.

Next we 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.

The “PrintDocument2” is the name of the Print Document control that was added they need to match.  The “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) ” .

The “ 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 Draw string event to draw  the (Sting 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 a 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:

Original C# article

MSDN sites:

Graphics Methods

Graphics Class

How to: Create Graphics Objects for Drawing

Getting Started with Graphics Programming

Advertisements

About pcsxcetrasupport3

My part time Business, I mainly do system building and system repair. Over the last several years I have been building system utility's in vb script , HTA applications and VB.Net to be able to better find the information I need to better understand the systems problems in order to get the systems repaired and back to my customers quicker.
This entry was posted in CodeProject, VB.net and tagged , . Bookmark the permalink.

3 Responses to Windows form screenshot and print preview in VB.Net

  1. sir plz send the coding of online tourism management in vb.net projects.

  2. Savoxit says:

    thanks so much…
    it’s so usefull for me

Comments are closed.