|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic
Window/Form Routines Pure VB: Customizable PhotoShop-Style ProgressBar |
||
Posted: | Saturday April 26, 1997 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB4-32, VB5, VB6 | |
Developed with: | VB3, Windows 3.1 | |
OS restrictions: | None | |
Author: | VBnet - Randy Birch | |
Related: |
SetParent: Add a VB Progress Bar to a VB StatusBar SendMessage: Change the Colour of a VB ProgressBar Pure VB: Customizable PhotoShop-Style ProgressBar in a MDI App CreateWindowEx: Creating a Common Control Progress Bar - Overview CreateWindowEx: Creating the Common Control Flood Panel via the API SetParent: Display Modal Form Activity on a Parent Form's 'PhotoShop-style' Progress Bar SetParent: Display Modal Form Activity in a Parent Form's VB Progress Bar |
|
Prerequisites |
None. |
|
The
routines on this page were originally developed to overcome display limitations of the original VB3 SSPanel FloodPercent control,
namely use of and justification of text and the positioning the control as a member
of a status panel. The routine was originally developed in VB3 and
has been updated for use under all later versions of 32-bit VB. The methodologies remain more than viable alternatives to the standard flood/status
panels provided.
The inspiration Adobe PhotoShop whose status panel indicates the progress of an operation by displaying a text message overtop the progress indicator with the reversed text colour to remain readable. The following code can be easily integrated into any existing project where a fully-customizable status panel is required. By using a picture box without borders or 3D effects and sizing it to a status panel, the original Adobe status panel is easily duplicated. Despite the complicated form shown above, the actual implementation uses just one sub to perform the drawing of the text and progress, and a single picture box for the output. The size of the code here is due to my presenting the basic flood update routine in four flavours: percentage readout only, centred text only, left justified text with the percentage trailing, and positional text routine (my Favourite). The illustration to the left is just a collage of several screen shots showing the effect using different options; there's no need to actually create this form. The differences in the values between each example is due to capturing each mode using print screen while running. Notes: The "BitBlit" caption on the "BitBlt Demo" button in the demo was a throwback to the original VB3 code, which required the data to be copied to the picture box via API. The API is no longer required, so for all intents and purposes it should now simply say "Test". |
BAS Module Code |
None. |
|
Form Code |
Although the actual routine is relatively straightforward,
to create this demo, start a new project with a form add a
picture box to become the flood window (tbFlood),
along with five command buttons (Command1, Command2, Command3, Command4 and Command5). Next, add an option button array of four buttons (optFloodColour(0) - optFloodColour(3)), and a second option array of three buttons inside a frame or second picture box and name these controls optTextPosition(0) - optTextPosition(2). The demo illustration uses a frame with the BorderStyle set to 0. Add a label over the picture box (Label1) just to reflect the action taking place. To easily demonstrate the appearance of different strings as the flood message, add a combo box (Combo1) set to type 0
to allow you to type in your own message. |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private floodPos As Long Private Sub Form_Load() 'position the form 1/3 up the screen Me.Move (Screen.Width - Me.Width) \ 2, (Screen.Height - Me.Height) \ 3 'set the flood's initial attributes 'white text (trust me, I know it says backcolor !) tbFlood.BackColor = &HFFFFFF tbFlood.DrawMode = 10 'solid fill tbFlood.FillStyle = 0 tbFlood.AutoRedraw = True 'required to prevent flicker! 'initialize the controls Combo1.AddItem "Loading user preferences ... please wait." Combo1.AddItem "Loading ... please wait." optFloodColour(0).Value = True optTextPosition(0).Value = True Combo1.ListIndex = 0 Command1.Caption = "BitBlit Demo" Command2.Caption = "Percent Only" Command3.Caption = "Text && Percent" Command4.Caption = "Positioned Text" Command5.Caption = "End" End Sub Private Sub Command5_Click() Unload Me End Sub Private Sub Command1_Click() Label1.Caption = "PhotoShop Progress Panel inversion demo ..." FloodUpdatePercent 100, 48 End Sub Private Sub Command2_Click() Dim cnt As Long Dim unit As Long Dim upperLimit As Long Dim progress As Long 'The tbFloodUpdatePercent sub requires 3 pieces of information: ' - the upperlimit of the items to count to. ' - the total progress-to-date. ' - the increment unit used to update the progress. 'There are several ways of doing this: you could ' - pass upperLimit and value, and store static progress in the sub; ' - pass upperLimit and progress, and perform the math in ' each routine calling the flood (as shown below); or ' - pass all three variables back and forth 'The upperLimit is the number of things to count to. 'For example, if you are counting a 1534-record 'random access file, the code might be: ' upperLimit = LOF(#MyFile) / MyType 'For demo purposes, a limit of 250 is used 'The 'unit' is the counting increment - typically this 'would be one (as in once each record), but can be 'changed to reflect actions in chunks. ''progress' is the total accumulated thus far. unit = 1 upperLimit = 1000 Label1.Caption = "Processing..." For cnt = 1 To upperLimit '(your code for some method goes here) 'update the status display progress = progress + unit FloodUpdatePercent upperLimit, progress Next Label1.Caption = "Complete." End Sub Private Sub Command3_Click() Dim cnt As Long Dim unit As Long Dim upperLimit As Long Dim progress As Long unit = 1 upperLimit = 1000 Label1.Caption = "Processing..." For cnt = 1 To upperLimit '(your code for some method goes here) 'update the status display progress = progress + unit FloodUpdateTextPC upperLimit, progress, (Combo1.Text) Next Label1.Caption = "Complete." End Sub Private Sub Command4_Click() Dim cnt As Long Dim unit As Long Dim upperLimit As Long Dim progress As Long unit = 1 upperLimit = 1000 Label1.Caption = "Processing..." For cnt = 1 To upperLimit '(your code for some method goes here) 'update the status display progress = progress + unit FloodUpdateText upperLimit, progress, (Combo1.Text) Next Label1.Caption = "Complete." End Sub Private Sub optFloodColour_Click(Index As Integer) 'set the floodcolour by setting the ForeColor !! Select Case Index Case 0: tbFlood.ForeColor = &H0& 'black Case 1: tbFlood.ForeColor = &H800000 'blue Case 2: tbFlood.ForeColor = &H80& 'red Case 3: tbFlood.ForeColor = &H808000 'teal End Select End Sub Private Sub optTextPosition_Click(Index As Integer) floodPos = Index End Sub Private Sub FloodUpdatePercent(upperLimit As Long, progress As Long) Dim msg As String 'make sure that the flood display hasn't already hit 100% If progress <= upperLimit Then 'error trap in case the code attempts 'to set the scalewidth greater than 'the max allowable If progress> tbFlood.ScaleWidth Then progress = tbFlood.ScaleWidth End If 'erase the flood tbFlood.Cls 'set the ScaleWidth equal to the upper limit of the items to count tbFlood.ScaleWidth = upperLimit 'format the progress into a percentage string to display msg = Format$(CLng((progress / tbFlood.ScaleWidth) * 100)) + "%" 'calculate the string's X & Y coordinates 'in the PictureBox ... here, centered tbFlood.CurrentX = (tbFlood.ScaleWidth - tbFlood.TextWidth(msg)) \ 2 tbFlood.CurrentY = (tbFlood.ScaleHeight - tbFlood.TextHeight(msg)) \ 2 'print the percentage string in the text colour tbFlood.Print msg 'print the flood bar to the new progress length in the line colour tbFlood.Line (0, 0)-(progress, tbFlood.ScaleHeight), tbFlood.ForeColor, BF 'allow the flood to complete drawing DoEvents End If End Sub Private Sub FloodUpdateTextPC(upperLimit As Long, progress As Long, msg As String) Dim r As Long Dim pc As String If progress <= upperLimit Then If progress > tbFlood.ScaleWidth Then progress = tbFlood.ScaleWidth End If tbFlood.Cls tbFlood.ScaleWidth = upperLimit 'format the progress into a percentage string to display pc = Format$(CLng((progress / tbFlood.ScaleWidth) * 100)) + "%" 'calculate the string's X & Y coordinates 'in the PictureBox ... here, left justified and offset slightly tbFlood.CurrentX = 2 tbFlood.CurrentY = (tbFlood.ScaleHeight - tbFlood.TextHeight(msg)) \ 2 'print the percentage string in the text colour tbFlood.Print msg & " " & pc 'print the flood bar to the new progress length in the line colour tbFlood.Line (0, 0)-(progress, tbFlood.ScaleHeight), tbFlood.ForeColor, BF DoEvents End If End Sub Private Sub FloodUpdateText(upperLimit As Long, progress As Long, msg As String) Dim r As Long If progress <= upperLimit Then If progress > tbFlood.ScaleWidth Then progress = tbFlood.ScaleWidth End If tbFlood.Cls tbFlood.ScaleWidth = upperLimit 'calculate the string's X & Y coordinates 'in the PictureBox based on the floodPos set Select Case floodPos Case 0 'left tbFlood.CurrentX = 2 tbFlood.CurrentY = (tbFlood.ScaleHeight - tbFlood.TextHeight(msg)) \ 2 Case 1 'centered tbFlood.CurrentX = (tbFlood.ScaleWidth - tbFlood.TextWidth(msg)) \ 2 tbFlood.CurrentY = (tbFlood.ScaleHeight - tbFlood.TextHeight(msg)) \ 2 Case 2 'right tbFlood.CurrentX = (tbFlood.ScaleWidth - tbFlood.TextWidth(msg)) - 3 tbFlood.CurrentY = (tbFlood.ScaleHeight - tbFlood.TextHeight(msg)) \ 2 End Select 'print the string in the 'at the position set above tbFlood.Print msg 'print the flood bar to the new 'progress length in the line colour tbFlood.Line (0, 0)-(progress, tbFlood.ScaleHeight), tbFlood.ForeColor, BF DoEvents End If End Sub |
Comments |
The Command1 button simply sets the tbFlood to 48%
completed, to illustrate what the output will look like. The remaining command buttons activate the different flood Update methods.
Practically, in a final app you would normally chose just one method for use throughout the application.
The speed of the progress bar is a product of the upper limit, and the
current count cycle. For example, a call with an upper limit of 100,000
and a step ratio of 1 will take a few seconds to run, whereas a call with
an upper limit of 100 with the same ratio will complete faster.
Similarly, a step ratio of 10 will cause the bar to run faster than a
ratio of 1.
Because you are, in effect, setting the BackColor for the text and the ForeColor for the background, certain colour combinations can lead to rather interesting results. In practical use, you may want to consider the addition of two additional routines coded below. In my implementation, I used one status panel (of an SSPanel) for text display during the course of the app running. Into this panel I placed the tbFlood as well, and only made it visible when there was a need to indicate a long running process. Therefore, I needed routines to hide and display the tbFlood as needed. My solution was place all the flood-related code into a BAS module, and to code two additional routines that were called before and after each tbFlood usage: Public Sub FloodDisplay (upperLimit As Integer) parentForm!tbFlood.Cls parentForm!tbFlood.Visible = True parentForm!tbFlood.ScaleWidth = upperLimit parentForm!tbFlood.CurrentX = upperLimit * .03 End Sub Public Sub FloodHide () parentForm!tbFlood.Visible = False parentForm!tbFlood.Cls End Sub 'To use these routines, I called them in routines as: FloodDisplay TotalClients msg = "Retrieving Client Data .." For cnt = 1 To TotalClients Get #ClientFileNo, cnt, Client FloodUpdate cnt, msg '(your code for some method goes here) Next cnt FloodHide |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |