A friend of mine asked me to make him a little app that would take a screen shot of any URL and save it as a jpeg.
Hmmm, I thought, not having done very much with GDI and drawing classes and mostly developing web projects. I knew this would need a windows application to take the screen shot, so I set about trying to build this up.
Et Voila! Only version 1, but this one will take an inputted URL, produce a preview and then allow the user to resize and save the screen shot as a jpeg on their computer.
So, how to do...
First of all I found some cool GDI code on the .Net forums by clyde1. It was in C# so I first needed to convert it to VB and tweak a little.
The resulting class takes a screen shot of an input URL - resizes and produces a bitmap of the page.
*****
Imports Microsoft.VisualBasic
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Drawing.Drawing2D
Public Class Screenshot
Private screenWidth As Integer
Private screenHeight As Integer
Private browser As WebBrowser = New WebBrowser()
Public Sub New ( ByVal screenWidth As Integer , ByVal screenHeight As Integer )
Me .screenWidth = screenWidth
Me .screenHeight = screenHeight
browser.ScrollBarsEnabled = False
browser.Size = New Size(screenWidth, screenHeight)
End Sub
Public Function Fetch( ByVal url As String , ByVal width As Integer , ByVal height As Integer ) As Bitmap
browser.Navigate(url)
While browser.ReadyState <> WebBrowserReadyState.Complete
Application.DoEvents()
End While
Dim bitmap As Bitmap = New Bitmap(screenWidth, screenHeight)
Dim rectangle As Rectangle = New Rectangle(0, 0, screenWidth, screenHeight)
browser.DrawToBitmap(bitmap, rectangle)
Dim imgOutput As Image = bitmap
Dim screenshot As Bitmap = New Bitmap(width, height, imgOutput.PixelFormat)
Dim graphics As Graphics = Drawing.Graphics.FromImage(screenshot)
graphics.CompositingQuality = CompositingQuality.HighSpeed
graphics.SmoothingMode = SmoothingMode.HighSpeed
graphics.InterpolationMode = InterpolationMode.HighQualityBilinear
Dim rect As Rectangle = New Rectangle(0, 0, width, height)
graphics.DrawImage(imgOutput, rect)
Try
Return screenshot
Finally
bitmap.Dispose()
graphics.Dispose()
End Try
End Function
End Class
*****
Then to call this from the main form we add this to the event handler for the 'generate screen shot' button.
I then use Drawing.Image to convert the bitmap to a thumbnail image and show it in the picture box.
*****
Public Class Form1
Dim Mus As MyAppSettings
Private Sub btnSS_Click( ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSS.Click
lblSSInfo.Text = "Generating..."
lblSSInfo.ForeColor = Color.SlateGray
Dim y As Bitmap = GetBitmap(TxtUrl.Text)
' Save thumbnail and output it onto the webpage
Dim myCallBack As System.Drawing.Image.GetThumbnailImageAbort
myCallBack = New System.Drawing.Image.GetThumbnailImageAbort( AddressOf FunctionName)
'resize to thumnail
Dim mythumbnail As System.Drawing.Image
mythumbnail = y.GetThumbnailImage(308, 264, myCallBack, IntPtr.Zero)
PBSS.Image = mythumbnail
lblSSInfo.Text = "Generated"
lblSSInfo.ForeColor = Color.Firebrick
End Sub
Public Function GetBitmap( ByVal url As String )
Dim x As Screenshot = New Screenshot(800, 600)
Dim screenshot As Bitmap = x.Fetch(url, 800, 800)
Return screenshot
End Function
End Class
*****
Next we need to add the event handler for the "SaveScreen Shot" button. Again, I resize it according to user input and save to the chosen directory.
*****
Private Sub btnSave_Click( ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
lblSaveInfo.Text = "saving..."
lblSaveInfo.ForeColor = Color.SlateGray
' generates the jpeg and resizes it
Dim y As Bitmap = GetBitmap(TxtUrl.Text)
' Save thumbnail and output it onto the webpage
Dim myCallBack As System.Drawing.Image.GetThumbnailImageAbort
myCallBack = New System.Drawing.Image.GetThumbnailImageAbort( AddressOf FunctionName)
'resize to thumnail
Dim mythumbnail As System.Drawing.Image
mythumbnail = y.GetThumbnailImage(txtWidth.Text, TxtHeight.Text, myCallBack, IntPtr.Zero)
If Not Txtname.Text = "" Then
mythumbnail.Save(lblSavePath.Text & "\" & Txtname.Text & ".jpg" , System.Drawing.Imaging.ImageFormat.Jpeg)
Else
mythumbnail.Save(lblSavePath.Text & "\" & "unknown.jpg" , System.Drawing.Imaging.ImageFormat.Jpeg)
End If
lblSaveInfo.Text = "saved"
lblSaveInfo.ForeColor = Color.Firebrick
Mus.IHeight = TxtHeight.Text
Mus.IWidth = txtWidth.Text
Mus.SavePath = lblSavePath.Text
Mus.Save()
End Sub
Public Function FunctionName() As Boolean
'This handles the getThumnailimageabort
Return False
End Function
*****
Another interesting piece of winForms programming I learnt here was the use of <UserScopedSetting()> _
These allow you to save users settings and I needed this to save the users prefered width and height as well as their prefered save path.
This is the class I used:
*****
Imports System.Configuration
Public Class MyAppSettings
Inherits ApplicationSettingsBase
<UserScopedSetting()> _
<DefaultSettingValue( "white" )> _
Public Property BackgroundColor() As Color
Get
BackgroundColor = Me ( "BackgroundColor" )
End Get
Set ( ByVal value As Color)
Me ( "BackgroundColor" ) = value
End Set
End Property
<UserScopedSetting()> _
<DefaultSettingValue( "C:\program files\" )> _
Public Property SavePath() As String
Get
SavePath = Me ( "SavePath" )
End Get
Set ( ByVal value As String )
Me ( "SavePath" ) = value
End Set
End Property
<UserScopedSetting()> _
<DefaultSettingValue( "267" )> _
Public Property IWidth() As String
Get
IWidth = Me ( "IWidth" )
End Get
Set ( ByVal value As String )
Me ( "IWidth" ) = value
End Set
End Property
<UserScopedSetting()> _
<DefaultSettingValue( "200" )> _
Public Property IHeight() As String
Get
IHeight = Me ( "IHeight" )
End Get
Set ( ByVal value As String )
Me ( "IHeight" ) = value
End Set
End Property
End Class
*****
I could then easily save values the user entered from the main form like so:-
Mus.IHeight = TxtHeight.Text
Mus.IWidth = txtWidth.Text
Mus.SavePath = lblSavePath.Text
Mus.Save()
----------------------------------------------
Next step is to create a section that allows for a multiple number of URLs to be entered and a jpeg produced for each one.
I used the tab control to show another page for this function [shown below]
Here's how...
All I needed to do was to allow the user to paste in csv into a textbox, then using the split function, I was able to create an array of successfully split URLs and saved jpegs. Here's the code for the event
******
Private Sub btnMultiSave_Click( ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMultiSave.Click
Dim aryUrls As Array
Dim i As Integer = 0
aryUrls = Split(TxtMultiURLs.Text, (vbCrLf))
For i = 0 To UBound(aryUrls)
'process each image
lblmultiInfo.Text = "saving..."
lblMultiInfo.ForeColor = Color.SlateGray
' generates the jpeg and resizes it
Dim z As Bitmap = GetBitmap((aryUrls(i)))
' Save thumbnail and output it onto the webpage
Dim myCallBack As System.Drawing.Image.GetThumbnailImageAbort
myCallBack = New System.Drawing.Image.GetThumbnailImageAbort( AddressOf FunctionName)
'resize to thumnail
Dim mythumbnail As System.Drawing.Image
mythumbnail = z.GetThumbnailImage(TxtMultiWidth.Text, TxtMultiHeight.Text, myCallBack, IntPtr.Zero)
Try
If Not TxtMultiName.Text = "" Then
mythumbnail.Save(lblMultiSavePath.Text & "\" & TxtMultiName.Text & "_" & i & ".jpg" , System.Drawing.Imaging.ImageFormat.Jpeg)
Else
mythumbnail.Save(lblMultiSavePath.Text &
"\unkown_" & i & ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg)
End If
lblMultiInfo.Text = "saved"
lblMultiInfo.ForeColor = Color.Firebrick
Mus.IMultiHeight = TxtMultiHeight.Text
Mus.IMultiWidth = TxtMultiWidth.Text
Mus.MultiSavePath = lblMultiSavePath.Text
Mus.Save()
txtresults.Text = txtresults.Text + (aryUrls(i)) & vbCrLf
Catch ex As Exception
txtresults.Text = txtresults.Text + ex.ToString
lblMultiInfo.Text = "error"
End Try
Next
End Sub
*****
All comments gratefully received. Jack
*****