Have you ever copied a large number of files, or downloaded something big using IE? If so, you’ve probably seen the taskbar download progress indicator. This is a green progress bar that fills the area behind the application icon in the taskbar.
You can achieve the same effect in Windows 7 using .NET 4, with very little code. Let’s run through how.
Project Setup
I created a simple WPF application in Visual Studio 2010. Nothing fancy, I kept the original MainWindow and simply worked with that. I named the project “Win7ProgressBar”.
Next I added an icon to the project. I have a C64 logo icon I created for my Silverlight C64 emulator handy, so I used that.
MainWindow
I resized the main window to be a little smaller, gave it the title “Long Task” and assigned the icon to it. The resulting opening tag looks like this:
<Window x:Class="Win7ProgressBar.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Long Task" Height="241" Width="432"
Icon="/Win7ProgressBar;component/AppIcon032.png">Next, I added a progress bar and a textblock to the window:
<Grid>
<ProgressBar Height="23"
HorizontalAlignment="Left"
Margin="36,88,0,0"
Name="progressBar1"
VerticalAlignment="Top"
Width="334" />
<TextBlock Height="23"
HorizontalAlignment="Left"
Margin="36,24,0,0"
Name="textBlock1"
Text="This is a really long-running task"
VerticalAlignment="Top"
Width="201" />
</Grid>Here’s how the window looks in the VS2010 designer.
So far so good. I have a window and a progress bar, but no activity, and nothing that would as yet hook it up to the taskbar.
Taskbar wireup isn’t automatic; it’s something you need to opt into. You can do it in xaml, and you can do it in code. I used a mixture of both for this example. Since we still have the window xaml open, let’s put that in there now.
Right after the opening tag for the window, and before the opening grid tag, add in this snip:
<Window.TaskbarItemInfo>
<TaskbarItemInfo />
</Window.TaskbarItemInfo>That simply news up a TasbarItemInfo class for us. If you look at the TasbarItemInfo tag, you’ll see there’s quite a bit more you can do right from within xaml. But I always do everything in xaml, so let’s try some code instead :)

An aside on ClearType
The rather ugly font in the drop down is due to the settings on the monitor on which I took this shot (I have three displays). I need to readjust my cleartype settings for that display. If you have crappy-looking fonts in apps, you can simply go to Control Panel –> Fonts and then select the option to adjust the cleartype settings on your monitor.
Run through the wizard and answer the questions for which one looks best. You’re better off not thinking and simply acting. The more you think about the answer, the less accurate you’ll be. Go with your first impressions.
By way of comparison, here’s the same thing, only snapped from my primary monitor, with good cleartype settings:
Notice the massive difference in the drop-down list? If not, scroll back up and look again.
Now, most people won’t have to go through that wizard unless they get a drastically different display from what they started with. I needed to simply because I tested a special build of SL3 before it went live, and was specifically asked to look at the cleartype rendering. I played with the wizard and forgot to go back and fix it :)
Back to the TaskBar
Now that we have all the xaml in place, let’s take a look at the code. I’m going to simulate a long-running activity simply by throwing in a background worker and having it run a tight loop with a bunch of thread sleeps in there.
Wire up the loaded event handler for the window, and let the IDE help you wire up the events for DoWork, ProgressChanged, RunWorkerCompleted.
Next, be sure to set the worker.WorkerReportsProgress to true, and then call the RunWorkerAsync() method to kick off the process. The resulting load event looks like this:
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.WorkerReportsProgress = true;
worker.RunWorkerAsync();
}Before we start reporting progress to the taskbar and the progress bar, let’s set the starting ProgressState for the taskbar. You can set this multiple times throughout the life of the process to control various states. Here’s what the states look like:
Normal (green progress bar)
Indeterminate (pulsing green wave)
Paused (yellow progress bar)
Error (red progress bar)

So, let’s start it off at Normal. You could do this in the loaded event or in the constructor, or at any point during the process. I initialized it in the constructor.
public MainWindow()
{
InitializeComponent();
TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Normal;
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
Next, we need to handle reported background thread process status and use it to update both the progress bar in the window and the taskbar. That’s really simple to do. Note, however, that the TaskbarItemInfo.ProgressValue is a double between 0 and 1 while the progressBar value is an integer between two numbers supplied by you (typically 0 and 100), so we’ll need to adjust when we report progress.
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
TaskbarItemInfo.ProgressValue = (double)e.ProgressPercentage/100;
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar1.Value = 100;
TaskbarItemInfo.ProgressValue = 1.0;
}Finally, we need our worker itself. This is where you’d be doing something real, and time-consuming. Instead, I’ll just do something really time-consuming :) It sleeps one second per iteration and then reports the current progress.
void worker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 100; i += 10)
{
Thread.Sleep(1000);
((BackgroundWorker)sender).ReportProgress(i);
}
}Runtime
When you run the app, you’ll see both the window and the taskbar update.

That was really easy. There are other things you can do with TaskbarItemInfo, such as changing your thumbnail and adding overlay icons. We’ll look at those in an upcoming post.
A Word on Use
Be judicious with how you use progress reporting on Windows 7. You should only use it when the progress status will be meaningful to a user when running other applications. Consider the scenario of your app doing something that the user will typically alt-tab away from. If the app is doing something that the user will want to know when it has completed so they can take an action (like opening a downloaded zip) then the taskbar progress reporting will be good. If, however, you are doing something which will have other progress indicators (like playing a video, where it’s obvious when the video ends because the user can see/hear it) or which won’t have the user waiting with bated breath for it to finish, consider just using a regular old progress bar, preferably a non-modal one.
A video version of those, with source code, will be available on windowsclient.net I’ll update this post with a link once that is up.
Update 12/16/2009: The video and source code are located here.