PJ on Development
Thoughts and babbling about software development. Visual Basic, .NET platform, web, etc.
Title: | ProgressDialog Class |
Description: | Using the Windows native progress dialog. |
Author: | Paulo Santos |
eMail: | pjondevelopment@gmail.com |
Environment: | Windows (Win2003, Win2K, WinXP), .NET 2.0, Visual Studio 2005, COM |
Keywords: | User Interface, Control, Dialog, Progress Dialog |
ProgressDialog Class
- Download Source Code - 93,08 KB
DISCLAIMERThe Software is provided "AS IS", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and non-infringement. in no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software. |
||
Introduction
This code is a by-product of a bigger project. In my project I needed a way of informing the user of the progress of a said task. Searching over the net I found the initial component created by sytelus, that uses a TypeLib file to create an Interop layer. By other hand, Russkie, in his project created a wrapper purely in C#.
However, although I do like C#, I feel more comfortable working in VB. So, I started porting Russkie's project to Visual Basic.
Background
I would like to call your attention to the indication that this VB version is compatible only with .NET 2.0 as stated on top of this page. It's not that I don't want to develop using .NET 1.1 the problem is that VB7 has a bug regarding the use of ComImport as can be seen on MSDN.
Although on MSDN they say that this bug affects only VB.NET 2002 it also affects the 2003 version, one more reason for the use of Visual Studio 2005.
A Different Approach
Russkie's component is a great implementation, no doubt, but it uses some concepts that, in my humble opinion, feel a little bit awkward.
For instance, when the method Start
is called it not only shows the ProgressDialog but it also goes through a iterative loop calling the Callback Delegate
that should process whatever function is needed.
My approach to this problem is a little bit straightforward: the main loop starts the ProgressDialog at the beginning, updates the progress value while in process (noting the process cancellation by the user), and finally closes de dialog.
His implementation also relies on the Flags
property, which is a map of bits. Although I kept the Flags
property, I also added a few properties that are easier recognizable than a cryptic Flags
property.
ProgressDialog members
Public Enumerators
dlgAnimations Lists all available default animations. Public Enum dlgAnimations As UShort Custom = 0 SearchFlashlight = 150 SearchDocument = 151 SearchComputer = 152 FileMove = 160 FileCopy = 161 ToRecycleBinDelete = 162 FromRecycleBinDelete = 163 PermanentDelete = 164 FlyingPapers = 165 SearchGlobe = 166 FileMove95 = 167 FileCopy95 = 168 FileDelete95 = 169 InternetCopy = 170 NoAnimation = UShort.MaxValue End Enum | |
dlgLines Defines all available lines. Public Enum dlgLines As Byte LineOne = 1 LineTwo = 2 LineThree = 3 End Enum |
Public Constructors
ProgressDialog Constructor Initializes a new instance of the ProgressDialog Class. Public Sub New(ByVal f As Form) Public Sub New(ByVal hWnd As intPtr) |
Public Properties
Animation Gets or sets the animation played by the dialog window while processing. Public Property Animation() As dlgAnimationsNote: Setting this property after the dialog is being shown has no effect. | |
AutomaticRemainingTime Gets or sets if the remaining time should be calculated automatically. Public Property AutomaticRemainingTime() As BooleanNote: Setting this property after the dialog is being shown has no effect. | |
CancelMessage The message to be displayed if the cancellation process needs to take time. Public Property CancelMessage() As StringNote: Setting this property after the dialog is being shown has no effect. | |
Complete Gets or sets the amount of the job done. Public Property Complete() As ULong | |
HideProgressBar Gets or sets the flag that displays the progress bar. Public Property HideProgressBar() As BooleanNote: Setting this property after the dialog is being shown has no effect. | |
HideRemainingTime Gets of sets the flag that displays the remaining time. Public Property HideRemainingTime() As BooleanNote: Setting this property after the dialog is being shown has no effect. | |
IsModal Gets or sets the flag that forces the progress window to be modal. Public Property IsModal() As BooleanNote: Setting this property after the dialog is being shown has no effect. | |
Title The Title to be displayed on the title bar of the dialog. Public Property Title() As String | |
Total Gets or sets the total size of the job. Public Property Total() As ULong | |
UserCancelled A System.Boolean flag that indicates if the user has cancelled the process. Public ReadOnly Property UserCancelled() As Boolean |
Public Methods
ResetTimer Resets the internal timer. Public Sub ResetTimer() | |
SetCustomAnimation Defines the custom animation to be used. Public Sub SetCustomAnimation( _ ByVal hLibrary As IntPtr, _ ByVal resNumber As UShort) This method takes the instance handle specified by hLibrary and uses the common control's animation control to open and run a silent AVI clip. There are several restrictions as to what types of AVI clips can be used:
Note: The SetCustomAnimation function requires a pointer to a library and the number of the resources to be used. It is beyond the scope of this documentation how to acquire such information. | |
SetLineText Sets the text to be displayed in one of the three available lines. Public Sub SetLineText(ByVal Line As dlgLines, _ ByVal Text As String, _ Optional ByVal CompactPath As Boolean) | |
Start Display the dialog and resets the internal timer. Public Sub Start() | |
Stop Closes the dialog. Public Sub Stop() |
Using the code
As I stated, using this class is pretty straightforward as can be seen on the function below.
Private Sub DoSomethingLong() '* '* Create a new instance of the ProgressDialog Class '* Dim pd As New ProgressDialog(Me) '* '* Initialize the Dialog Properties '* With pd .Complete = 0 .Total = 10000 .Title = "Title" .Animation = _ ProgressDialog.dlgAnimations.PermanentDelete End With '* '* Starts the Dialog '* pd.Start() '* '* Do something long '* For i As UInteger = 1 To 10000 pd.Complete += 10 pd.SetLineText(ProgressDialog.dlgLines.LineTwo, _ "Item No." & i) '* '* Checks for user cancellation '* If (pd.UserCancelled) Then Exit For End If System.Threading.Thread.Sleep(50) Next '* '* Closes the dialog '* pd.Stop() End Sub
I hope you find this code useful in your projects.
How to use a custom AVI
So far, the only way to use a custom animation is to create an external resource dll and use the following code snippet.
Private Enum llFlags As UInteger DontResolveDllReferences = &H1 LoadLibraryAsDatafile = &H2 LoadWithAlteredSearchPath = &H8 LoadIgnoreCodeAuthzLevel = &H10 End Enum <DllImport("kernel32", _ CharSet:=CharSet.Auto, _ SetLastError:=True)> _ Private Shared Function LoadLibraryEx( _ <MarshalAs(UnmanagedType.LPTStr)> _ ByVal lpFileName As String, _ ByVal hFile As IntPtr, _ ByVal dwFlags As LoadLibraryExFlags) As IntPtr End Function Private Function ShowProgress() Dim pd as New ProcessDialog Dim hLibrary as IntPtr '* '* Defines a custom animation '* hLibrary = LoadLibraryEx( _ "YOUR_RESOURCE_DLL_HERE" & Chr(0), _ IntPtr.Zero, _ llFlags.DontResolveDllReferences Or _ llFlags.LoadLibraryAsDatafile) If (hLibrary <> IntPtr.Zero) Then pd.Animation = ProgressDialog.dlgAnimations.Custom pd.SetCustomAnimation(hLibrary, _ YOUR_RESOURCE_NUMBER_HERE) End If '* '* Now you may show the '* ProgressDialog as '* instructed above. '* End Function