A Flexible Progress Window in VBScript19 Jul 2009
I’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
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 -
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