A Flexible Progress Window in VBScript
19 Jul 2009I’ve seen a few variations over the years on how to create a progress bar and an update window in VBScript. I’ve taken many of the ideas and some of my own to create what I hope is a flexible solution that not only allows you to display updates, reports, etc., but also a reasonable looking progress bar. If you want to skip ahead then the code is at the bottom of this post and includes an example, but for those of you who want to know a little more about how to use it or how it works I’ll explain some of the whys and wherefores.
First of all I’ve created this progress window as a class. This means
that (certainly from a programming perspective at the least) everything
is presented neatly and if necessary you can create a multiple
instances. So the first thing to do is to create a new instance using
New ProgressWindow
. After doing this you then use the Initialise
method for your object to create the window.
The window is a Microsoft Internet Explorer window. I’ve chosen this because an HTML page allows me the greatest amount of flexibility in what to display and MSIE s found on pretty much every PC - although the recent EU / Microsoft dealings mean that the European version of Windows 7 may be bereft of this browser by default. When initialising the window, you get parameters to specify a title, the size (width & height in pixels) and also a number of regions.
Each region is a section of the HTML page and you can independently
update each region independently. Because of this you can enter the
content as HTML. This allows you to not only enter text, but also
create tables, insert images, hyperlinks, etc. The method to use to set
the content of a region is UpdateRegion
. There are also a couple of
methods to clear one or all regions - ClearRegion
and
ClearAllRegions
respectively.
The last area to be explained is the progress bar. The “UpdateRegionProgress” method takes three parameters. The first identifies which region is to host the progress bar. The second parameter is the percentage of the progress bar that should be filled. The final parameter is used to set the length of the progress bar (by number of characters). The method doesn’t include any option to add anything before or after the progress bar, but it would be a simple modification to add in parameters for prefix and suffix HTML.
The method also has four constants that allow you to specify the characters to be used to form the progress bar and the colours of the characters. This could be changed to any valid HTML and so you could specify images to be loaded for your progress bar.
The example code creates the progress window with three regions and populates them each with text. The third region shows a simple example of HTML “rich” text with a word picked out in bold. After a couple of seconds the second region’s text is updated. Within a couple more seconds the content is cleared and then a new message is put into the first region. The second and third regions are then set to display progress as a loop increments between 0 and 100. The second region displays the progress as a numeric percentage whereas the third region displays this as a progress bar. After a couple more seconds the window closes. The images below show what this looks like.
The initial window has three regions.
Each region’s content can be changed independently of the other regions.
The third region shows a progress bar.
So just drop the ProgressWindow class into your script and you’re ready to display your script progress.
Option Explicit
'Instantiate a progress window with three regions
Dim objThing
Set objThing = new ProgressWindow
objThing.Initialise "This is an example progress window", 4, 750, 250
'First population of window
objThing.UpdateRegion 1, "This is the first region"
objThing.UpdateRegion 2, "... wait for it ..."
objThing.UpdateRegion 3, "This is the third region"
WScript.Sleep 2000
'Show that we can simply update an individual region
objThing.UpdateRegion 2, "This is the second region"
WScript.Sleep 2000
'Clear everything and then put a new message up
objThing.ClearAllRegions
objThing.UpdateRegion 1, "This window will close in a few seconds..."
'This loop shows how to use a progress bar 60 characters long
Dim intPercentage
For intPercentage = 0 to 100
objThing.UpdateRegion 2, "Progress: " & intPercentage & "%"
objThing.UpdateRegionProgress 3, intPercentage, 60
WScript.Sleep 75
Next
'Pause for a couple of seconds then get rid of the progress window
WScript.Sleep 2000
objThing.Destroy
'################
'#### CLASSES ###
'################
'Create an instance of this class to create a progress window based on an HTML page
'displayed in an Internet Explorer window.
Class ProgressWindow
'Progress Window Properties
Dim intWidth
Dim intHeight
Dim intRegions
Dim strTitle
Dim objProgress
'Create the progress window
'The first parameter is the title of the progress window.
'The second parameter is the number of regions on the page you wish to be able to update independently.
'The third parameter is the width of the window in pixels.
'The fourth parameter is the height of the window in pixels.
Sub Initialise(p_strTitle, p_intRegions, p_intWidth, p_intHeight)
'Set class properties
strTitle = p_strTitle
intRegions = p_intRegions
intWidth = p_intWidth
intHeight = p_intHeight
'Create the progress window
CreateMSIEWindow objProgress
End Sub
'Display the basic window
Sub CreateMSIEWindow(p_objMSIE)
Dim strHTML
Dim intCounter
strHTML = ""
For intCounter = 1 to intRegions
strHTML = strHTML & ""
Next
strHTML = "" & strHTML & ""
Set p_objMSIE = CreateObject("InternetExplorer.Application")
With p_objMSIE
.Navigate2 "about:blank"
Do While .readyState <> 4
Wscript.sleep 10
Loop
.Document.Title = strTitle
.Document.Body.InnerHTML = strHTML
.Document.Body.Scroll = "no"
.Toolbar = False
.StatusBar = False
.Resizable = False
.Width = intWidth
.Height = intHeight
.Left = 0
.Top = 0
.Visible = True
End With
End Sub
'This should be called to close the window
Sub Destroy()
objProgress.Quit
End Sub
'This method can be used to update the content of a specified region
Sub UpdateRegion(p_intRegion, p_strContent)
objProgress.Document.All("REGION" & Cstr(p_IntRegion)).innerHTML = p_strContent
End Sub
'This method clears a specified region.
Sub ClearRegion(p_intRegion)
UpdateRegion p_intRegion, ""
End Sub
'This method clears all of the regions at once.
Sub ClearAllRegions()
Dim intRegion
For intRegion = 1 to intRegions
UpdateRegion intRegion, ""
Next
End Sub
'Set a progress bar as a region...
'The first parameter is which region.
'The second parameter is the percentage completion of the bar.
'The third parameter is the number of characters that make up the bar.
Sub UpdateRegionProgress(p_intRegion, p_intPrecentageProgress, p_intCharacterRange)
'These constants are used to create the progress bar
Const SOLID_BLOCK_CHARACTER = "?"
Const EMPTY_BLOCK_CHARACTER = "?"
Const SOLID_BLOCK_COLOUR = "#ffcc33;"
Const EMPTY_BLOCK_COLOUR = "#666666;"
Dim intSolidBlocks, intEmptyBlocks, intCounter
Dim strProgress
'Calculate how many blocks we need to create
intSolidBlocks = round(p_intPrecentageProgress / 100 * p_intCharacterRange)
intEmptyBlocks = p_intCharacterRange - intSolidBlocks
intCounter = 0
'Build the progress so far blocks
strProgress = ""
While intCounter < intSolidBlocks
strProgress = strProgress & SOLID_BLOCK_CHARACTER
intCounter = intCounter + 1
Wend
strProgress = strProgress & ""
'Build the progress to be met blocks
strProgress = strProgress & ""
intCounter = 0
While intCounter < intEmptyBlocks
strProgress = strProgress & EMPTY_BLOCK_CHARACTER
intCounter = intCounter + 1
Wend
strProgress = strProgress & ""
'Set the specified region to be the blocks
UpdateRegion p_intRegion, strProgress
End Sub
End Class