Visual StudioOne of the things I like with new versions of Windows is the possibility of new features for developers. Windows 7, like Vista, seems to include a few little things for us to play about with, namely the ITaskbarList3 Interface exposed by the Windows Shell.

ITaskbarList3

This is an Interface exposed by the Shell32.dll library that provides API functions for launching and adding switching taskbar button functionality, in addition to displaying thumbnail representations of tabs in a tabbed application, thumbnail toolbars, notification and status overlays, and – what we’re primarily interested in – progress indicators.

I installed the Windows 7 Beta a little while back as I was interested in making use of the progress indicator display exposed by the Shell in my own applications. For those that haven’t seen this in action, here’s a screen-grab of YouChoob’s taskbar entry (the right-most icon) while downloading a video…

YouChoob's download progress within Window 7's taskbar

YouChoob has downloaded 50% of the video; as you can see, the downloaded percentage is reflected within the background of YouChoob’s taskbar entry. With the inclusion of the file at the end of this post, adding such a feature to your application is very easy.

ITaskbarList3::HrInit

This is the very first call you must make before any other calls detailed below. It initialises the Taskbar list object for use. There is no de-initialisation equivalent required at the end of program execution.

ITaskbarList3::SetProgressState(windowHandle, flag)

This allows you to specify which state your progress bar is in to Explorer. Here are the flags that can be passed, along with simplified descriptions of them.

  • TBPF_NOPROGRESS: Stops displaying any progress information and returns the taskbar entry back to its default state. This should be called when your application’s progress has completed.
  • TBPF_INDERTERMINATE: Displays a marquee that constantly cycles from left to right to show that the application is busy, but it has no estimation on how long it will be busy for.
  • TBPF_NORMAL: Displays a standard green progress bar that goes from left to right, indicating a growing percentage.
  • TBPF_ERROR: Displays a red progress bar that indicates an error has occurred.
  • TBPF_PAUSED: Turns the progress bar yellow indicating that it is currently paused.

ITaskbarList3::SetProgressValue(windowHandle, currentProgress, totalProgress)

This is the method that will be getting called the most from your code as it updates the percentage (and ultimately the size of the bar) that is displayed on your application’s taskbar entry. The totalProgress parameter isn’t just a value from 0 to 100, but instead the raw value that denotes what value currentProgress must be for completion. For example, if you’re downloading a file that is 4,096 bytes in size, the totalProgress value will be 4,096 and currentProgress will be starting from 0 and working its way up to that 4,096 value.

Example Code Overview

What we’re going to be doing in the example code below is initialise the taskbar object, display an ever-increasing progress bar over the course of a 25 second time period, and then dismiss the progress bar when we’re finished. Examples for both VB.Net (WinForms) and C# (WPF) are listed.

SetProgressState and SetProgressValue requires the handle to the window that “owns” the progress information as their first parameter.

Example Code – VB.Net WinForms

‘ Create an instance of the TaskbarList for use.
Dim taskList As New TaskbarLib.TaskbarList

‘ Initialise the Tasklist so we can call its methods.
taskList.HrInit()

‘ Put the progress bar in its Normal state.
taskList.SetProgressState(myForm.Handle, TaskbarLib.TBPFLAG.TBPF_NORMAL)

‘ Do a standard 1 to 100 loop.
For index As Integer = 1 To 100

‘ Increment the progress bar by the new index value.
taskList.SetProgressValue(myForm.Handle, index, 100)

‘ Simulate some work being done by sleeping for 250ms.
Threading.Thread.Sleep(250)

Next

‘ Dismiss the progress bar from the taskbar entry now that we’re done with it.
taskList.SetProgressState(myForm.Handle, TaskbarLib.TBPFLAG.TBPF_NOPROGRESS)

Example Code – C# WPF

// Obtain a handle to our current window via the interop helper as WPF
// doesn’t natively expose the Handle property.
int handle = new System.Windows.Interop.WindowInteropHelper(this).Handle.ToInt32();

// Create an instance of the TaskbarList for use.
TaskbarLib.TaskbarList taskList = new TaskbarLib.TaskbarList();

// Initialise the Tasklist so we can call its methods.
taskList.HrInit();

// Put the progress bar in its Normal state.
taskList.SetProgressState(handle, TaskbarLib.TBPFLAG.TBPF_NORMAL);

‘ Do a standard 1 to 100 loop.
for (ulong index = 1; index < 100; index++) {

// Increment the progress bar by the new index value.
taskList.SetProgressValue(handle, index, 100);

// Simulate some work being done by sleeping for 250ms.
System.Threading.Thread.Sleep(250);

}

// Dismiss the progress bar from the taskbar entry now that we’re done with it.
taskList.SetProgressState(handle, TaskbarLib.TBPFLAG.TBPF_NOPROGRESS);

ITaskbarList3 In Previous Versions of Windows

Trying to use any of the ITaskbarList3 features in any version of Windows prior to 7 will result in a standard application crash. To get around this, you’ll need to check to make sure that your app is running in Windows 7 or higher before making any calls to the new interface. You could do this in various ways; here’s a simple method that returns a True or False determining if the current OS is Windows 7 or higher. The comparisons haven’t been short-circuited due to reasons of clarity.

Edit: Thanks to Larry Osterman, I’ve fixed a very stupid error in the version check code, although Larry’s posting goes a bit far saying that version checking “is hard”. My excuse is: I was pissing around in a language I’m not familiar with while not really paying attention to what I was writing (a bit of a dialogue was happening within the comments I was trying to keep up with). In addition, I’ve removed the VB code rather than rewrite it as Wordpress is driving me mad when I want nicely formatted code.

// Simple example in C#; you can cache the return result or whatever should you so wish.
internal bool SupportsTaskProgress() {
if (System.Environment.OSVersion.Version.Major == 6) {
return (System.Environment.OSVersion.Version.Minor >= 1);
} else {
return (System.Environment.OSVersion.Version.Major > 6);
}
}

In Conclusion

Windows 7 provides a way for developers to display progress information while their application isn’t being directly displayed or is obscured. To begin using this functionality, extract the file below and reference it in your solution within Visual Studio.

Download: TaskbarLib.dll

Feel free to buy me a beer if you like this post!