Programming the Task Bar in Windows 7 with WPF 4, Part Four – Progress

Bar Icons

By Alessandro Del Sole – Microsoft MVP

Download the code

Read the entire series of articles here: Programming the Windows 7 Task Bar with WPF 4

Introduction

Showing the progress of a task is important in every application’s UI. This gives users the right perception of
the amount of time required for completing a particular operation. For example, when you download a file
from the Internet, whichever Web browser you use the browser itself shows a dialog that displays the
download percentage and the remaining time. In most .NET applications the UI element used for showing
the progress of a task is the ProgressBar control and this is true for WPF as well. The only limitation is that
you need to open the application’s active window in order to check the task progress. Fortunately Windows
7 introduces another improvement, known as Progress Bar Icons; such a feature allows utilizing the
application’s icon on the task bar like a fully functional progress bar so that users can see progress without
activating the application. Moreover progress bar icons can show faults in the task progress. Figure 1 shows
an example related to an instance of Internet Explorer while downloading a file from the Internet.

Figure 1 – The Internet Explorer’s progress bar icon

In this article I will describe how to easily implement progress bar icons in WPF 4 applications with Visual
Studio 2010.

Creating the sample project

In real world applications there are so many different situations in which you need to show the progress of
a task. Because of this, the code for the sample application will just show the progress of time passing. The
example will focus on how you enable progress bar icons and how you change the appearance of such icons
according to the progress state. The application will show some progress within a ProgressBar control
exposed by the main Window and on the application’s icon. The first step is to create a new WPF project
with Visual Basic 2010 (or Visual C#4.0). Once the IDE’s designer is ready, we can write the simple user
interface.

Defining the User Interface in XAML

Just like the previous articles of the series, in order to interact with Windows 7’s task bar you need a
TaskbarItemInfo object. Also, for this particular example the application requires a ProgressBar control.
Listing 1 shows the XAML code for the sample application.

<Window x:Class="MainWindow"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Window.TaskbarItemInfo>
        <TaskbarItemInfo/>
    </Window.TaskbarItemInfo>
 
    <Grid>
        <ProgressBar Name="ProgressBar1" Height="40" Margin="5"/>
    </Grid>
</Window>

Listing 1 – Defining the user interface

Most of the work is made on the code-behind side, so you need to open the MainWindow.xaml.vb code
file.

Understanding Progress States

You specify icons as progress bar icons by assigning the TaskbarItemInfo.ProgressState property with one of
the values exposed by the System.Windows.Shell.TaskbarItemProgressState enumeration. Available values
are the following:

  1. Normal: progress bar icon is green and enabled for showing progress
  2. Error: progress bar icon gets colored in red and is used for communicating faults while progressing
  3. Paused: progress bar icon gets colored in yellow and is used when the progress is paused
  4. Indeterminate: progress bar icon is again colored in green and display progress intermittently; it is
    used for communicating an idle state or that an input from the user is requested

There is also a None value which is the default value, but generally you use Normal. Let’s begin by
implementing a normal state progress. Later in the article I will describe the other states.

Displaying progress on the icon

The sample code basically wastes some time in an asynchronous way, sending the progress percentage to
both the ProgressBar on the Window and the progress bar icon. To accomplish this, we can use a
BackgroundWorker control which is useful for asynchronous operations and for multithreading in WPF. The
progress of such a control will be sent to progress bars. If you are not familiar with the BackgroundWorker
control, you can check out the MSDN documentation for this control. Code in Listing 2 demonstrates how
to reach the proposed objective.

Imports System.ComponentModel
 
Class MainWindow
 
    Dim WithEvents worker As BackgroundWorker
 
    Private Sub Window_Loaded(ByVal sender As System.Object, 
                              ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
        Me.worker = New BackgroundWorker
        'Enable progress reporting
        worker.WorkerReportsProgress = True
 
        'Set the progress state as "normal"
        TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Normal
 
        'Start the work
        worker.RunWorkerAsync()
    End Sub
 
    Private Sub worker_DoWork(ByVal sender As Object, 
                             ByVal e As System.ComponentModel.DoWorkEventArgs) Handles worker.DoWork
        'Wasting some time asynchronously
        For i As Integer = 0 To 99 Step 10
            System.Threading.Thread.Sleep(1000)
 
            'Raises the ProgressChanged event passing the value
            CType(sender, System.ComponentModel.BackgroundWorker).ReportProgress(i)
        Next i
    End Sub
 
    'Increment the value on both progress bars
    Private Sub worker_ProgressChanged(ByVal sender As Object, 
       ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles worker.ProgressChanged

        ProgressBar1.Value = e.ProgressPercentage
        TaskbarItemInfo.ProgressValue = CDbl(e.ProgressPercentage) / 100
    End Sub
 
    'Work completed, maximum value is set
    Private Sub worker_RunWorkerCompleted(ByVal sender As Object, 
       ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted

        ProgressBar1.Value = 100
        TaskbarItemInfo.ProgressValue = 1.0
    End Sub
End Class

Listing 2 – Enabling progress bar icons and displaying progress

The above code presents two points of interest. The first one is the following line of code:

'Set the progress state as "normal"
        TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Normal

The code tells the task bar that the progress bar icon will show the progress in a normal state, thus green.
The second point of interest is about the assignment of the TaskbarItemInfo.ProgressValue property like
this:

TaskbarItemInfo.ProgressValue = CDbl(e.ProgressPercentage) / 100
...
TaskbarItemInfo.ProgressValue = 1.0

This means that you display the progress by assigning the above mentioned property with a value of type
Double. If you now run the application, you will get a result as shown in Figure 2.

Figure 2 – The sample application shows progress on the application’s icon

This is the case of a normal progress state. There are situations in which you need to show an error in
progress or simply capture the user attention with a different progress state. Let’s see how we can do that
next.

Indeterminate state

Imagine your application reaches an idle state or that you need to request an action from the user while
the progress is running or your application encounters a temporary problem. In such situations it can be
useful to communicate to the user that the operation in progress is temporarily unavailable. To accomplish
this, the System.Windows.Shell.TaskbarItemProgressState enumeration provides the Indeterminate value
which makes the progress bar icon run intermittently. To provide an example, replace the
worker_RunWorkerCompleted event handler with the one shown in Listing 3.

'Work completed, maximum value is set
    Private Sub worker_RunWorkerCompleted(ByVal sender As Object, 
     ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted

        ProgressBar1.Value = 100
        TaskbarItemInfo.ProgressValue = 1.0
 
        TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Indeterminate
        Dim result = MessageBox.Show("The progress completed. Would you like to exit now?", 
                                     "", MessageBoxButton.YesNo)
        If result = MessageBoxResult.Yes Then Application.Current.Shutdown()
    End Sub

Listing 3 – Showing an indeterminate progress state

In this case the application is requesting an action from the user once the progress completes, putting the
progress bar icon on the Indeterminate state. Figure 3 shows an example.

Figure 3 – Showing an indeterminate progress state

You can take advantage of progress bar icons for displaying errors too, as demonstrated in next section.

Paused and Error states

You can take advantage of the progress bar icon for displaying an error or paused state. This is
accomplished by assigning the TaskbarItemInfo.ProgressState property with either the
TaskbarItemProgressState.Error or TaskbarItemProgressState.Paused values. Code in Listing 4
demonstrates how to handle both scenarios by rewriting the worker_RunWorkerCompleted event handler.

'Work completed, maximum value is set
    Private Sub worker_RunWorkerCompleted(ByVal sender As Object, 
     ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted

        If e.Cancelled = True Then
            Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Paused
        ElseIf e.Error IsNot Nothing Then
            Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Error
        Else
            ProgressBar1.Value = 100
            TaskbarItemInfo.ProgressValue = 1.0
        End If
    End Sub

Listing 4 – Handling Paused and Error states

It is worth mentioning that in the sample application you need to invoke the worker.CancelAsync method
in order to make the e variable value change to Cancelled. Figure 4 shows how the progress bar icon
appears in the error state.

Figure 4 – the Error state

In the case of the Paused state, the progress bar icon gets colored in yellow.

Conclusion

Progress bar icons are a great improvement in Windows 7 providing a very useful way for giving users the
perception of how the application is progressing without having to open the application window. WPF 4
makes it easy to program this feature as well as many other new features in Windows 7.

About the author

Alessandro Del Sole is a Microsoft Visual Basic MVP and Team Member in the Italian “Visual Basic Tips &
Tricks
” Community. He writes many Italian and English language community articles and books about .NET
development and is the author of the book “Visual Basic 2010 Unleashed”. He also enjoys writing freeware
and open-source developer tools. You can visit Alessandro’s Italian language blog or his English language blog.