cDialogProgress class
A cDialogProgress keeps the state of a long task: a position between a minimum and a maximum, the time spent and an estimate of the time left, a message, and whether the task was cancelled. It raises events when the position changes or the task is cancelled, and describes the state as a line of text.
The class shows no window. In version 1.1.0.0 it has no dialog, no progress bar and no cancel button, whatever its name, Title, ShowCancel, Style and OwnerHwnd suggest. A program that wants to show the progress reads Percentage or GetDescription and draws them itself, for instance on a form, and calls Cancel from its own button. ShowProgress writes the description with Debug.Print, which appears in the debug console of the IDE and nowhere in a built program.
A cDialogProgress is made with New: Dim progress As New cDialogProgress. It cannot be made with CreateObject. To receive the events, declare a variable WithEvents.
Start begins a task. Progress, Increment, PerformStep, SetPercentage and Complete move the position, each raising ProgressChanged. Cancel sets Cancelled, which the task has to test: nothing stops a task by itself, and only SimulateProgress looks at the flag.
Dim progress As New cDialogProgress
Dim i As Long
progress.Message = "Copying files"
progress.Max = 200
progress.Start
For i = 1 To 200
If progress.Cancelled Then Exit For
' ... copy file i ...
progress.Progress = i
Next i
If Not progress.Cancelled Then progress.Complete
Debug.Print progress.Percentage & "%"
Note
GetRemainingTime, and with it GetRemainingTimeString and GetDescription, raise error 11 (Division by zero) when they are called before the clock has ticked after Start (the clock of Windows ticks about every 16 milliseconds) and Progress is above Min. A program that reports progress as it begins reads the description too early. Call them later, or handle the error.
Note
Percentage and SetPercentage multiply in a Long, so a range wider than about 21 million units can raise error 6 (Overflow): Percentage with Max 100,000,000 and a position of 50,000,000 does, and so does SetPercentage with 50. Use a smaller range, such as the number of items instead of the number of bytes.
Properties
Cancelled
Whether Cancel was called, read-only.
Syntax: object.Cancelled As Boolean
False in a new object. Cancel sets it to True; Start and Reset set it to False.
Dim progress As New cDialogProgress
Debug.Print progress.Cancelled ' False
progress.Cancel
Debug.Print progress.Cancelled ' True
progress.Start
Debug.Print progress.Cancelled ' False
DetailMessage
A second line of text for GetDescription.
Syntax: object.DetailMessage [ = value ]
- value
- A String. The default is an empty string.
GetDescription adds it on a new line when it is not empty.
Dim progress As New cDialogProgress
progress.Style = ProgressStyle.Marquee
progress.Message = "Copying"
progress.DetailMessage = "report.txt"
Debug.Print Replace(progress.GetDescription(), vbCrLf, " | ") ' Copying | report.txt
Max
The value of Progress at the end of the task.
Syntax: object.Max [ = value ]
- value
- A Long. The default is 100.
Changing it does not move Progress. A value that is not above Min makes Percentage 0.
Dim progress As New cDialogProgress
Debug.Print progress.Max ' 100
progress.Max = 250
Debug.Print progress.Max ' 250
Message
The main text of GetDescription.
Syntax: object.Message [ = value ]
- value
- A String. The default is
Processing....
Dim progress As New cDialogProgress
Debug.Print progress.Message ' Processing...
Min
The value of Progress at the start of the task.
Syntax: object.Min [ = value ]
- value
- A Long. The default is 0.
Start sets Progress to it. Changing it does not move Progress.
Dim progress As New cDialogProgress
progress.Min = 10
progress.Max = 110
progress.Start
Debug.Print progress.Progress ' 10
Debug.Print progress.Percentage ' 0
OwnerHwnd
A property that has no effect.
Syntax: object.OwnerHwnd [ = value ]
- value
- A LongPtr. The default is 0.
The value is stored; there is no window to own. Unlike the other properties, Reset keeps it.
Dim progress As New cDialogProgress
progress.OwnerHwnd = 1234
progress.Reset
Debug.Print progress.OwnerHwnd ' 1234
Percentage
The position as a percentage of the range, read-only.
Syntax: object.Percentage As Long
(Progress - Min) * 100 \ (Max - Min), rounded down; 0 when Max is not above Min. A position below Min, which Increment can reach with a negative Step, gives a negative number. See the second note above for a range that is too wide.
Dim progress As New cDialogProgress
progress.Progress = 40
Debug.Print progress.Percentage ' 40
progress.Max = 200
Debug.Print progress.Percentage ' 20
progress.Max = 0
Debug.Print progress.Percentage ' 0
Progress
The position of the task.
Syntax: object.Progress [ = value ]
A value outside the range is ignored, without an error or an event. Any other value, even the current one, is stored and raises ProgressChanged. The default is 0.
Dim progress As New cDialogProgress
progress.Progress = 40
Debug.Print progress.Progress ' 40
progress.Progress = 150 ' above Max: ignored
Debug.Print progress.Progress ' 40
progress.Progress = -1 ' below Min: ignored
Debug.Print progress.Progress ' 40
ShowCancel
Whether ShowProgress adds a line on cancelling.
Syntax: object.ShowCancel [ = value ]
- value
- A Boolean. The default is True.
With True, ShowProgress ends its text with (Press Ctrl+Break to cancel). The class does not react to that key; a task is cancelled by a call to Cancel.
Dim progress As New cDialogProgress
Debug.Print progress.ShowCancel ' True
ShowElapsedTime
Whether GetDescription names the time spent.
Syntax: object.ShowElapsedTime [ = value ]
- value
- A Boolean. The default is True.
Dim progress As New cDialogProgress
Debug.Print progress.ShowElapsedTime ' True
ShowRemainingTime
Whether GetDescription names the estimated time left.
Syntax: object.ShowRemainingTime [ = value ]
- value
- A Boolean. The default is True.
Dim progress As New cDialogProgress
Debug.Print progress.ShowRemainingTime ' True
Step
The amount by which Increment moves Progress.
Syntax: object.Step [ = value ]
- value
- A Long. The default is 1.
SimulateProgress uses it as the step of its loop.
Dim progress As New cDialogProgress
progress.Step = 25
progress.Increment
progress.Increment
Debug.Print progress.Progress ' 50
Style
The kind of progress that GetDescription describes.
Syntax: object.Style [ = value ]
- value
- A ProgressStyle member. The default is ProgressBar.
With ProgressBar, GetDescription adds the percentage and the times. With Marquee or Steps it returns the message alone, with the detail line.
Dim progress As New cDialogProgress
Debug.Print progress.Style = ProgressStyle.ProgressBar ' True
progress.Style = ProgressStyle.Steps
Debug.Print progress.Style ' 2
Title
A property that has no effect.
Syntax: object.Title [ = value ]
- value
- A String. The default is
Progress.
The value is stored. The class shows no title bar and does not use it in its text.
Dim progress As New cDialogProgress
Debug.Print progress.Title ' Progress
Methods
Cancel
Marks the task as cancelled.
Syntax: object.Cancel
Sets Cancelled to True and raises CancelClicked. It stops nothing: the task has to test Cancelled. Cancelling a task that was already cancelled raises the event again.
Dim progress As New cDialogProgress
progress.Cancel
Debug.Print progress.Cancelled ' True
Complete
Moves the position to the end.
Syntax: object.Complete
Sets Progress to Max and raises ProgressChanged with that value, also when Progress was already there.
Dim progress As New cDialogProgress
progress.Max = 80
progress.Complete
Debug.Print progress.Progress ' 80
Debug.Print progress.Percentage ' 100
GetDescription
Returns the state as a line of text.
Syntax: object.GetDescription ( ) As String
Returns Message. With Style ProgressBar it adds (N%) with Percentage; then - Elapsed: and GetElapsedTimeString when ShowElapsedTime is True, and - Remaining: and GetRemainingTimeString when ShowRemainingTime is True and Progress is above Min. A non-empty DetailMessage follows after vbCrLf. See the first note above for the error that the remaining time can raise.
Dim progress As New cDialogProgress
progress.Message = "Copying"
progress.DetailMessage = "report.txt"
progress.Progress = 50
Debug.Print Replace(progress.GetDescription(), vbCrLf, " | ")
' Copying (50%) - Elapsed: 0:00 - Remaining: 0:00 | report.txt
progress.ShowElapsedTime = False
progress.ShowRemainingTime = False
Debug.Print Replace(progress.GetDescription(), vbCrLf, " | ")
' Copying (50%) | report.txt
GetElapsedTime
Returns the whole seconds since Start.
Syntax: object.GetElapsedTime ( ) As Long
0 before the first Start. The count is made from the clock of Windows, which wraps around to negative numbers after 24.8 days of uptime; while it is negative at Start, the time functions return 0.
Dim progress As New cDialogProgress
Debug.Print progress.GetElapsedTime() ' 0
GetElapsedTimeString
Returns the time since Start as text.
Syntax: object.GetElapsedTimeString ( ) As String
m:ss, or h:mm:ss from one hour on, such as 0:02 and 1:05:09.
Dim progress As New cDialogProgress
Debug.Print progress.GetElapsedTimeString() ' 0:00
GetRemainingTime
Estimates the whole seconds that are left.
Syntax: object.GetRemainingTime ( ) As Long
Takes the speed so far, (Progress - Min) per millisecond since Start, and returns the time that the rest of the range needs at that speed. Returns 0 before Start and while Progress is not above Min. It raises error 11 when no time has passed since Start; see the first note above.
Dim progress As New cDialogProgress
Debug.Print progress.GetRemainingTime() ' 0
GetRemainingTimeString
Returns GetRemainingTime as text.
Syntax: object.GetRemainingTimeString ( ) As String
In the form of GetElapsedTimeString.
Dim progress As New cDialogProgress
Debug.Print progress.GetRemainingTimeString() ' 0:00
Increment
Syntax: object.Increment
Adds Step to Progress and raises ProgressChanged. When the new value is above Max, nothing happens: no change and no event. The new value is not compared with Min, so a negative Step can lead below it.
Dim progress As New cDialogProgress
progress.Step = 40
progress.Increment
progress.Increment
progress.Increment ' 120 is above Max: ignored
Debug.Print progress.Progress ' 80
PerformStep
The same as Increment.
Syntax: object.PerformStep
Dim progress As New cDialogProgress
progress.PerformStep
Debug.Print progress.Progress ' 1
Reset
Restores the starting values.
Syntax: object.Reset
Sets Title to Progress, Message to Processing..., DetailMessage to an empty string, Progress and Min to 0, Max to 100, Step to 1, Style to ProgressBar, the three Show properties to True, Cancelled to False, and forgets Start. It raises no event and leaves OwnerHwnd as it is.
Dim progress As New cDialogProgress
progress.Max = 500
progress.Message = "Importing"
progress.Reset
Debug.Print progress.Max ' 100
Debug.Print progress.Message ' Processing...
SetPercentage
Moves Progress to a percentage of the range.
Syntax: object.SetPercentage ( percent )
- percent
- required A Long from 0 to 100. Another value is ignored, without an error or an event.
Sets Progress to Min + (Max - Min) * percent \ 100, rounded down, and raises ProgressChanged. See the second note above for a range that is too wide.
Dim progress As New cDialogProgress
progress.Min = 10
progress.Max = 110
progress.SetPercentage 25
Debug.Print progress.Progress ' 35
progress.SetPercentage 101 ' ignored
Debug.Print progress.Progress ' 35
progress.SetPercentage 100
Debug.Print progress.Progress ' 110
ShowProgress
Writes the description with Debug.Print.
Syntax: object.ShowProgress
Prints GetDescription, and when ShowCancel is True a blank line and (Press Ctrl+Break to cancel). It opens no window, and a built program shows nothing. It raises the error of GetDescription when that does.
Dim progress As New cDialogProgress
progress.Message = "Working"
progress.Progress = 30
progress.ShowProgress
SimulateProgress
Runs the task from the minimum to the maximum with a pause after every step, to try a program that reacts to the events.
Syntax: object.SimulateProgress ( [ delayMs ] )
- delayMs
- optional A Long, the pause after every step in milliseconds. The default is 100.
Calls Start, then for i from Min to Max in steps of Step: stops when Cancelled is True, sets Progress to i (raising ProgressChanged), calls ShowProgress and waits delayMs. Unless the task was cancelled it ends with Complete, so the last position is reported twice. The thread waits and does not process messages, so a handler of ProgressChanged is the place to call Cancel. A Step of 0 never ends unless the task is cancelled, and a negative one skips the loop, so that only Complete runs.
With a delayMs of 0 or 1 the call raises error 11 (Division by zero) at its second step, from the estimate of the remaining time; see the first note above. The default of 100 does not.
Dim progress As New cDialogProgress
progress.Max = 5
progress.SimulateProgress 50
Debug.Print "Done at " & progress.Percentage & "%"
Start
Begins a task.
Syntax: object.Start
Sets Progress to Min, Cancelled to False and notes the time for GetElapsedTime and GetRemainingTime. It raises no event, and does not change Message and the other texts.
Dim progress As New cDialogProgress
progress.Progress = 60
progress.Start
Debug.Print progress.Progress ' 0
Events
CancelClicked
Raised by Cancel.
Syntax: Event object.CancelClicked ( )
The handler runs before Cancel returns, and Cancelled is already True.
ProgressChanged
Raised when the position is set.
Syntax: Event object.ProgressChanged ( value )
- value
- The new position, a Long.
Raised by Progress for a value inside the range, Increment and PerformStep when they move, SetPercentage for a percentage inside 0 to 100, and Complete; also when the value is the same as before. Start and Reset raise nothing. The handler runs before the call returns.
A class that receives the events declares the variable with WithEvents:
Class ProgressLog
Private WithEvents mProgress As cDialogProgress
Public Sub Attach(ByVal source As cDialogProgress)
Set mProgress = source
End Sub
Private Sub mProgress_ProgressChanged(ByVal value As Long)
Debug.Print "changed to " & value
End Sub
Private Sub mProgress_CancelClicked()
Debug.Print "cancelled"
End Sub
End Class
This example counts the events of a short task. A value outside the range raises none, Complete raises one, and CancelClicked follows from Cancel:
Dim progress As New cDialogProgress
Dim log As New ProgressLog
log.Attach progress
progress.Max = 3
progress.Start
progress.Increment
progress.Increment
progress.Progress = 9 ' outside the range: no event
progress.Complete
progress.Cancel
' Output:
' changed to 1
' changed to 2
' changed to 3
' cancelled
Enumerations
ProgressStyle
The kinds of progress for Style. Only GetDescription reads it.
| Member | Value | Meaning |
|---|---|---|
| ProgressBar | 0 | A position in a range: the description has the percentage and the times |
| Marquee | 1 | A task of unknown length: the message alone |
| Steps | 2 | A task in steps: the message alone |
Example
This example reports the progress of a task as text every 25 per cent, and stops when the task is cancelled by a call from elsewhere in the program.
Dim progress As New cDialogProgress
Dim item As Long
progress.Message = "Processing items"
progress.Max = 100
progress.Step = 5
progress.Start
For item = 1 To 20
If progress.Cancelled Then Exit For
' ... process item ...
progress.PerformStep
If progress.Percentage Mod 25 = 0 Then Debug.Print progress.Percentage & "% done"
Next item
If progress.Cancelled Then
Debug.Print "Stopped at " & progress.Percentage & "%"
Else
progress.Complete
Debug.Print "Finished"
End If
See Also
- cDialogCountdownMsgBox class – shows a message box that closes by itself
- cDialogInputBox class – asks for one line of text
- TBMANLIB_Dialog package – overview