Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF: Integrating Our Application with the Windows 7 Taskbar (II)

0.00/5 (No votes)
3 Aug 2010 1  
Let your user interact with your application using the new features of the Windows 7 Taskbar

Introduction

In the previous article on integrating our application with the taskbar in Windows 7 (you can see it here), we talked about ways that gives us the Windows 7 taskbar to communicate information to our users, using the overlay of icons and progress bar.

Any program needs two-way communication, on one hand communicate information to the user and on the other users provide our application information with which to work, because we have managed to adapt to Windows 7 the way our users get information, we now make easily and intuitively that our user communicate information to us from the taskbar.

For this, in this article, we will discuss the JumpList and Thumbnail Toolbars:

  • Jumplist: The Jumplist are quick links to parts of our application that appears when you right click on the icon of it in the taskbar, we can make our app go directly to a particular window, without having started yet.
  • Thumbnail Toolbars: When you move the mouse over the icons of active applications, Windows 7 offers a preview of the window of that application, with the Thumbnail Toolbars we can add buttons to that view that execute in our application.

.NET 3.5 vs .NET 4

To access all these features, .NET 3.5 only had one way: Interoperability with unmanaged Win32 APIs (like the article on power management), however .NET 4 incorporates the functionality of the Windows 7 task bar in the framework itself, so that the "use and enjoyment" of these features is far easier. So the code in this article is only useful for .NET 4.

Let's Begin

Let's start. You must first create a new WPF Application project (File> New> Project), once established, we will design the main screen in the file MainWindow.xaml.

The styles that I used in this application are available in the download file Application.xaml. If you have questions about how to use / create styles, take a look at my two articles on this topic: here and here.

Well, to start working with the taskbar, we add an object to our XAML of type TaskbarItemInfo:

<Window.TaskbarItemInfo>
    <TaskbarItemInfo/>
</Window.TaskbarItemInfo>

With this, we will have access to many properties of the Windows 7 taskbar easily and quickly.

JumpList

Jumplist.PNG

We will start working with JumpList. The first thing we have to do is open the application.xaml code file and add a new event handler for the Startup event:

Private Sub Application_Startup(ByVal sender As Object, 
                                ByVal e As System.Windows.StartupEventArgs) 
                                Handles Me.Startup
End Sub

The way in which elements of the Jumplist will communicate with our application is by using arguments passed to the executable on start, so that in the Startup event will make two jobs, first check if we have received a parameter and run the code associated and in this event we will create our list and notify it to the application.

To handle the arguments passed to the application, will use the Args property of the e variable of the event, using a Select Case block to do so as follows:

If e.Args.Count > 0 Then
    Select Case e.Args(0)
        Case "update"
            MessageBox.Show("No updates needed")
        Case "searchclient"
            MessageBox.Show("You have picked Clients")
        Case "searchinvoice"
            MessageBox.Show("You have picked Invoices")
    End Select
End If

As you can see, it is very simple. When creating our JumpList to each element we have an associated argument (update, searchinvoice or searchclient), when selecting an item from the list, that element runs your application sending the argument that we have associated with.

Now we create the elements of the JumpList. For this, we will use the object JumpTask from the Shell namespace:

'Create our Jumplist Tasks
Dim SearchUpdates As New Shell.JumpTask
SearchUpdates.Title = "Search for Updates"
SearchUpdates.Arguments = "update"
SearchUpdates.Description = "Find new updates for the application"
SearchUpdates.CustomCategory = "Management"
SearchUpdates.IconResourcePath = Assembly.GetEntryAssembly().CodeBase
SearchUpdates.ApplicationPath = Assembly.GetEntryAssembly().CodeBase
Dim SearchClient As New Shell.JumpTask
SearchClient.Title = "Search clients"
SearchClient.Arguments = "searchclient"
SearchClient.Description = "Search the Clients database"
SearchClient.CustomCategory = "Clients"
SearchClient.IconResourcePath = Assembly.GetEntryAssembly().CodeBase
SearchClient.ApplicationPath = Assembly.GetEntryAssembly().CodeBase
Dim SearchInvoice As New Shell.JumpTask
SearchInvoice.Title = "Search Invoice"
SearchInvoice.Arguments = "searchinvoice"
SearchInvoice.Description = "Search the Invoices database"
SearchInvoice.CustomCategory = "Invoices"
SearchInvoice.IconResourcePath = Assembly.GetEntryAssembly().CodeBase
SearchInvoice.ApplicationPath = Assembly.GetEntryAssembly().CodeBase

Simply define the features of each JumpTask, now we only add them to a JumpList:

Dim List As New Shell.JumpList
List.JumpItems.Add(SearchUpdates)
List.JumpItems.Add(SearchClient)
List.JumpItems.Add(SearchInvoice)

Finally, we must tell the system to relate this list with your application, using the method SetJumpList of the class JumpList:

Shell.JumpList.SetJumpList(Application.Current, List)

Although this code will run whenever you start the application, the system will never duplicate JumpList elements. Whenever we pass a JumpList, it updates the elements that are assigned to our application, if we made a change, create new items or remove items no longer exist.

With this, if you run the application and press the right button on the taskbar icon, you will see the elements created by us, if you choose one, you'll see a corresponding message appears and opens a new instance of the application:

Jumplist2.PNG

Overall, giving our application a JumpList is not a complicated process, but ultimately it can give us many benefits. What happens to our users for multiple Windows to reach a data query or update, when we can offer more shares common with just two clicks and start your application directly to where our users need to go? If you think about it, sure, can you think of the thousands of situations where you were very comfortable having this system at hand. At least in my personal experience, this is one of the features of Windows 7 that I find most useful.

Thumbnail Toolbars

Toolbar.PNG

This way, the user interacts with our application combines seamlessly with the content of our previous article, in which we explained as informing the user of the progress of our application, but having the same window in sight. Well, with thumbnail Toolbars allowed, after receiving this information, the user can respond by executing an order in our application without the need to maximize the window.

The first thing we do is to create images for buttons, using the class DrawingImage as resources from our window:

<Window.Resources>
    <DrawingImage x:Key="IconUpdate">
        <DrawingImage.Drawing>
            <ImageDrawing Rect="0,0,24,24" ImageSource="/Images/update.png" />
        </DrawingImage.Drawing>
    </DrawingImage>
    <DrawingImage x:Key="IconClient">
        <DrawingImage.Drawing>
            <ImageDrawing Rect="0,0,24,24" ImageSource="/Images/client.png" />
        </DrawingImage.Drawing>
    </DrawingImage>
    <DrawingImage x:Key="IconInvoice">
        <DrawingImage.Drawing>
            <ImageDrawing Rect="0,0,24,24" ImageSource="/Images/invoice.png" />
        </DrawingImage.Drawing>
    </DrawingImage>
</Window.Resources>

The class we will use to create our buttons is the TaskBarItemInfo.ThumbButtonInfo:

<Window.TaskbarItemInfo>
    <TaskbarItemInfo>
        <TaskbarItemInfo.ThumbButtonInfos>
            <ThumbButtonInfo x:Name="btnUpdate"
                             ImageSource="{StaticResource IconUpdate}"
                             Description="Find updates for the application"
                             IsBackgroundVisible="True">
            </ThumbButtonInfo>
            <ThumbButtonInfo x:Name="btnClient"
                             ImageSource="{StaticResource IconClient}"
                             Description="Search Clients"
                             IsBackgroundVisible="True">
            </ThumbButtonInfo>
            <ThumbButtonInfo x:Name="btnInvoice"
                             ImageSource="{StaticResource IconInvoice}"
                             Description="Search Invoices"
                             IsBackgroundVisible="True">
            </ThumbButtonInfo>
        </TaskbarItemInfo.ThumbButtonInfos>
    </TaskbarItemInfo>
</Window.TaskbarItemInfo>

ThumbButtonInfo class has several properties that allow us to customize the look of our button:

  • Description: Indicates the text that appears on the button to leave the mouse over it.
  • IsInteractive: This property allows you to use a button in two ways:
    • True: The button behaves like a normal button, this is the default behavior.
    • False: The interactive button is only shown to the user, not reacting to the actions of this.
  • IsBackgroundVisible: Indicates whether the button is highlighted by positioning the mouse over it or not, the default is True.
  • DismissWhenClicked: If we set this property to True, when you press the button on, the Thumbnail will close, if False, it remains open until you leave the mouse icon on the taskbar, the default is False.

We have created our buttons. If you run the application and pass the mouse over the icon on the taskbar, you'll see three buttons appear that we have created, but if you click on them, nothing happens.

Now we set the behavior of buttons, this can be done in two ways: using events as any other button or by using commands.

The two methods can do the same job but perhaps is more advisable to use commands, as a rule these buttons will be the same as other buttons positioned on the main application toolbar or menu options and commands using the same code can link the two. I'll explain the two cases a bit more.

Using Events

The operation of the ThumbnailButtonInfo with events is very simple and exactly like the other controls in your application, simply add the event to which we respond from XAML:

<Window.TaskbarItemInfo>
    <TaskbarItemInfo>
        <TaskbarItemInfo.ThumbButtonInfos>
            <ThumbButtonInfo x:Name="btnUpdate"
                             ImageSource="{StaticResource IconUpdate}"
                             Description="Find updates for the application"
                             IsBackgroundVisible="True"
        Click="btnUpdate_Click">
            </ThumbButtonInfo>
            <ThumbButtonInfo x:Name="btnClient"
                             ImageSource="{StaticResource IconClient}"
                             Description="Search Clients"
                             IsBackgroundVisible="True"
        Click="btnClient_Click">
            </ThumbButtonInfo>
            <ThumbButtonInfo x:Name="btnInvoice"
                             ImageSource="{StaticResource IconInvoice}"
                             Description="Search Invoices"
                             IsBackgroundVisible="True"
        Click="btnInvoice_Click">
            </ThumbButtonInfo>
        </TaskbarItemInfo.ThumbButtonInfos>
    </TaskbarItemInfo>
</Window.TaskbarItemInfo>

As you can see, on each button we added a click event, now in code write the code needed for each event handler:

Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MessageBox.Show("Click on Update using events")
End Sub
Private Sub btnClient_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MessageBox.Show("Click on Clients using events")
End Sub
Private Sub btnInvoice_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MessageBox.Show("Click on invoice using events")
End Sub

With this, if we run our application and click on the buttons, the appropriate messagebox appears:

Toolbar2.PNG

Using Commands

This method involves a little more work, but it is much more representative of what an application would be doing. The first step is to create a new class for each button:

comandos1.PNG

As you can see, we have created a class for every action that we perform: Client, Invoice and Update. These classes must implement the ICommand interface to be used as commands in our application:

'UpdateCommand.vb
Public Class UpdateCommand
    Implements ICommand
    Public Function CanExecute(ByVal parameter As Object) As Boolean 
     Implements ICommand.CanExecute
        'TODO:Test if you can execute the command.
        Return True
    End Function
    Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) 
     Implements ICommand.CanExecuteChanged
    Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
        MessageBox.Show("Click on update button using Commands")
    End Sub
End Class
'ClientCommand.vb
Public Class ClientCommand
    Implements ICommand
    Public Function CanExecute(ByVal parameter As Object) As Boolean 
     Implements ICommand.CanExecute
        'TODO:Test if you can execute the command.
        Return True
    End Function
    Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) 
     Implements ICommand.CanExecuteChanged
    Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
        MessageBox.Show("Click on Clients Buttons using Commands")
    End Sub
End Class
'InvoiceCommand.vb
Public Class InvoiceCommand
    Implements ICommand
    Public Function CanExecute(ByVal parameter As Object) As Boolean 
     Implements ICommand.CanExecute
        'TODO:Test if you can execute the command.
        Return True
    End Function
    Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) 
     Implements ICommand.CanExecuteChanged
    Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
        MessageBox.Show("Click on Invoice Button Using Commands")
    End Sub
End Class

Next, what we need to do is have a common place from which to expose our commands, so that we can use the ViewModel, add a new class file to your project, called ViewModel and give it the following code:

Public Class ViewModel
    Private _UpdateCommand As UpdateCommand = New UpdateCommand()
    Private _ClientCommand As ClientCommand = New ClientCommand()
    Private _InvoiceCommand As InvoiceCommand = New InvoiceCommand()
    Public ReadOnly Property UpdateCommand As ICommand
        Get
            Return _UpdateCommand
        End Get
    End Property
    Public ReadOnly Property ClientCommand As ICommand
        Get
            Return _ClientCommand
        End Get
    End Property
    Public ReadOnly Property InvoiceCommand As ICommand
        Get
            Return _InvoiceCommand
        End Get
    End Property
End Class

Our ViewModel simply exposes public properties of the type of our commands to the view layer, the XAML in this case, so we just have to reference this in our XAML ViewModel and our DataContext:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModel="clr-namespace:WPF_JumpList_And_Thumbnail_Toolbars"
    Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <viewModel:ViewModel></viewModel:ViewModel>
    </Window.DataContext>
</Window>

Finally, we only need to link our buttons with their respective commands. For this, we will use the property Command of each ThumbButtonInfo:

<ThumbButtonInfo x:Name="btnUpdate"
                 ImageSource="{StaticResource IconUpdate}"
                 Description="Comprueba actualizaciones"
                 IsBackgroundVisible="True"
                 Command="{Binding UpdateCommand}">
</ThumbButtonInfo>
<ThumbButtonInfo x:Name="btnClient"
                 ImageSource="{StaticResource IconClient}"
                 Description="Ver los clientes"
                 IsBackgroundVisible="True"
                 Command="{Binding ClientCommand}">
</ThumbButtonInfo><ThumbButtonInfo x:Name="btnInvoice"
                 ImageSource="{StaticResource IconInvoice}"
                 Description="Ver las facturas"
                 IsBackgroundVisible="True"
                 Command="{Binding InvoiceCommnad}">
</ThumbButtonInfo>

As you can see, we are simply Binding to our command. If you execute the application again and you click a button, you can see that the effect is the same as with the events, only this time our code is more reusable and more orderly, it can share between multiple windows or controls the same command and keeping the same functionality:

Commandos2.PNG

History

  • 03 August 2010 - First version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here