Developing application with WPF and Windows 7 (Part II)
August 31st, 2009
In my previous post I talked about how to integrate some of the Windows 7 features (specifically Overlay Images and Taskbar Progress) in a WPF application we created for a screencast (in Spanish). In this post I will go over the remaining features I have yet to cover. These are:
- How to: Show a thumbnail of the application
- How to: Use Thumbnail Toolbar buttons
- How to: Open a new application with the Jumplist
Last time we ended up with this application, so you might be interested in downloading it, since all changes shown in this post will be done to it.
How to: Show a thumbnail of the application
One of the cool features in Windows 7, is that you can show a clipped thumbnail preview of your application instead of one for the entire window. We thought our application was identified by snowboards, so we decided to show the selected snowboard in the taskbar preview.
To set the custom preview, we are going to need the Window’s handle. However, as WPF Windows do not have a handle, we are going to add the following code in the Shell.xaml codebehind:
private IntPtr handle; public IntPtr Handle { get { if (this.handle == IntPtr.Zero) { WindowInteropHelper interopHelper = new WindowInteropHelper(this); this.handle = interopHelper.Handle; } return this.handle; } }
After that, we can add code like this in the Shell Load to clip our window and show the desired part of it:
private void Shell_OnLoad(object sender, RoutedEventArgs e) { this.InitializeConnectionMonitor(); this.InitializeRequestManager(); this.InitializeServiceAgent(); Rectangle clippingRect = new Rectangle( new System.Drawing.Point(552, 89), new System.Drawing.Size(210, 310)); Taskbar.TabbedThumbnail.SetThumbnailClip(this.Handle, clippingRect); }
As you can see, we hardcoded the values to clip the rectangle. However, you can simply calculate to obtain code that will work in any display.
If you run the application you should be able to see a small preview of the board when hovering over the application in the taskbar.
| Note: The thumbnail custom preview might not be visible in all versions of Windows 7. Running in VPC environment it also does not work. |
How to: Use Thumbnail Toolbar buttons
Thumbnail buttons are a really useful feature, because they allow you to execute different operations in your application without even having to open it. For the snowshop scenario we decided to add two buttons, one that would pick the next snowboard and another one for the previous.
We first need to define both buttons for the entire scope of the Shell.xaml class:
private readonly ThumbnailButton buttonPrevious; private readonly ThumbnailButton buttonNext;
In the Shell’s constructor we create the buttons and assign their respective icons:
public Shell() { this.InitializeComponent(); this.buttonNext = new ThumbnailButton(new Icon(“images\\nextArrow.ico”), “Next Image”); this.buttonPrevious = new ThumbnailButton(new Icon(“images\\prevArrow.ico”), “Previous Image”); }
Now we have to handle the click event of the buttons and add them. We placed this code in the Shell Load handler:
private void Shell_OnLoad(object sender, RoutedEventArgs e) { this.InitializeConnectionMonitor(); this.InitializeRequestManager(); this.InitializeServiceAgent(); Rectangle clippingRect = new Rectangle( new System.Drawing.Point(552, 89), new System.Drawing.Size(210, 310)); Taskbar.TabbedThumbnail.SetThumbnailClip(this.Handle, clippingRect); this.buttonNext.Click += this.ButtonNext_Click; this.buttonPrevious.Click += this.ButtonPrevious_Click; Taskbar.ThumbnailToolbars.AddButtons(this.Handle, this.buttonPrevious, this.buttonNext); }
As you might have noticed, the handlers for the events are yet to be written, so let’s get to it:
private void ButtonPrevious_Click(object sender, EventArgs e) { int newIndex = BoardList.SelectedIndex - 1; if (newIndex > -1) { this.BoardList.SelectedIndex = newIndex; } } private void ButtonNext_Click(object sender, EventArgs e) { int newIndex = BoardList.SelectedIndex + 1; if (newIndex < BoardList.Items.Count) { this.BoardList.SelectedIndex = newIndex; } }
But we also want to disable the Previous button when standing in the first board, and disable the Next button when the last board is selected. This can be easiliy achieved by adding the event handler declaration in XAML:
<ListBox x:Name=”BoardList” ItemsSource=”{Binding Source={StaticResource SnowboardTables}}” IsSynchronizedWithCurrentItem=”True” Style=”{StaticResource BoardListStyle}” SelectionChanged=”BoardList_SelectionChanged”/>
And writing code like this for the handler:
private void BoardList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { this.buttonPrevious.Enabled = this.BoardList.SelectedIndex > 0; this.buttonNext.Enabled = this.BoardList.SelectedIndex < BoardList.Items.Count - 1; }
As you can see adding code to interact with your applcation via Thumbnail Toolbar buttons is really straightforward, and if you press F5, you should be able to see the Snowboard in the Thumbnail preview spinning as your press the different thumbnail buttons to change the boards.
You can see an image below with the outcome of the application after both additions (Thumbnail Toolbar Buttons and Thumbnail image).

How to: Open a new application with the Jumplist
As you might have noticed the application allows you to sell more than one board at the same time, but it does not provide the total price of the purchase. That is why a feature that might come in handy is having the windows calculator launched from the application’s Jumplist . The Jumplist is like the application’s start menu, and many useful features can be implemented with it.
To use the Windows 7 Jumplist in your application, you first have to set the application’s ID, which is the unique identifier of your application (it is a string). The following code, which should be placed in the App.xaml file, will add a link to the calculator in the SnowShop’s jumplist:
protected override void OnStartup(System.Windows.StartupEventArgs e) { Taskbar.AppId = Settings.Default.AppID; JumpList jumpList = Taskbar.JumpList; CustomCategory helperCategory = new CustomCategory(“Shop Helpers”); jumpList.CustomCategories.Add(helperCategory); JumpListLink taskBarLink = new JumpListLink(); taskBarLink.Title = “Run Calculator”; taskBarLink.Path = @”%windir%\system32\calc.exe”; helperCategory.JumpListItems.Add(taskBarLink); jumpList.RefreshTaskbarList(); base.OnStartup(e); }
Outcome
You can download the code for the entire demo (including all the modifications explained in this post) from the link below.
Disclaimer
This code is provided “AS IS” with no warranties, and confers no rights.
Download
You can get source code here: SnowShopW7.zip.
I hope this couple of posts were useful for you when developing with WPF and Windows 7.
Developing applications with WPF and Windows 7 (Part I)
August 11th, 2009
Last week with Matias Woloski and Ezequiel Jadib we created a demo for a screencast (in Spanish) that shows how to take advantage of some Windows 7 features in a WPF application, improving the user experience (after all that is one of the main goals of WPF). You can find the code for the clean application (without Windows 7 functionality) here, and the fully functional application over here. In this and future posts I will go over the relevant additions to the application, so you can see how easy it is to take advantage of Windows 7 features in your existing application. At the end of each post I will provide the outcome solution.
Demo Scenario
The application shows a Snow Board Shop that allows to Ship Orders of different Snow Boards. It also provides support for temporarily connected scenarios using the Disconnected Service Agent Application Block from the Smart Client Software Factory.

The demo shows the following interaction with Windows 7:
- How to: Show connectivity status in the Windows 7 Taskbar [in this post]
- How to: Show progress while shipping orders [in this post]
- How to: Show a thumbnail of the application [coming soon]
- How to: Use Thumbnail buttons [coming soon]
- How to: Open a new application with the Jumplist [coming soon]
Implementation Details
- The demo leverages Windows 7 functionalities through the Microsoft.WindowsAPICodePack.dll and Microsoft.WindowsAPICodePack.Shell.dll. Downloaded from here (WindowsAPICodePack).
How to: Show connectivity status in the Taskbar
What we wanted to do is show whether the application is connected to the internet (which would in turn enable it to ship orders), without having the window open. What we decided to do is show an icon in the application’s taskbar that reflect the connectivity status. To do this, we must first add a reference to System.Drawing.dll and to both assemblies mentioned above (located in the Lib folder). Then, update the UpdateConnectionStatus method to change the icon based on the status:
private void UpdateConnectionStatus(bool isConnected) { string status; Icon icon; if (isConnected) { status = “Online”; icon = new Icon(“images\\Available.ico”); StatusLabel.Style = (Style)FindResource(“StatusLabelOnline”); StatusLabel.Content = status; } else { status = “Offline”; icon = new Icon(“images\\Offline.ico”); StatusLabel.Style = (Style)FindResource(“StatusLabelOffline”); StatusLabel.Content = status; } Taskbar.OverlayImage.Icon = icon; Taskbar.OverlayImage.Text = status; }
If you run the application now and connect/disconnect from the Internet, you will notice the icon in the Taskbar changing.
How to: Show progress while shipping orders
Now that we are able to show connectivity, and are working in a scenario with Offline capabilities it would be good to show the progress of the orders being dispatched without having the application’s window open. That’s when the Windows 7 taskbar comes to the rescue. Our goal is to show progress, by increasing the progress value as less orders are pending to dispatch. All we have to do is update the handlers of the RequestDispatched and RequestEnqueued events with code like this:
private delegate void OnRequestEnqueuedDelegate(object sender, RequestEnqueuedEventArgs e); private void OnRequestEnqueued(object sender, RequestEnqueuedEventArgs e) { this.UpdateRequestQueue(); if (Dispatcher.Thread != System.Threading.Thread.CurrentThread) { Dispatcher.Invoke(new OnRequestEnqueuedDelegate(OnRequestEnqueued), sender, e); } else { //Start showing progress when the first request is enqueued if (manager.RequestQueue.GetCount() == 1) Taskbar.ProgressBar.State = TaskbarButtonProgressState.Indeterminate; Taskbar.ProgressBar.MaxValue = manager.RequestQueue.GetCount(); Taskbar.ProgressBar.CurrentValue = 0; } } private delegate void OnRequestDispatchedDelegate(object sender, RequestDispatchedEventArgs e); private void OnRequestDispatched(object sender, RequestDispatchedEventArgs e) { this.UpdateRequestQueue(); if (Dispatcher.Thread != System.Threading.Thread.CurrentThread) { Dispatcher.Invoke(new OnRequestDispatchedDelegate(OnRequestDispatched), sender, e); } else { //Stop showing progress when there are no more requests if (manager.RequestQueue.GetCount() == 0) { Taskbar.ProgressBar.State = TaskbarButtonProgressState.NoProgress; } else { Taskbar.ProgressBar.State = TaskbarButtonProgressState.Normal; Taskbar.ProgressBar.CurrentValue += 1; } } }
To be able to see how this works, I would recommend disconnecting from the Internet (so no orders are dispatched) and enqueuing about 20 orders. Then connect, and you will be able to see the progress bar increasing as orders are dispatched.
Outcome
Disclaimer
This code is provided “AS IS” with no warranties, and confers no rights.
Download
You can get source code here: SnowShopPart1.zip.
Stay tuned because I will blog about all the other features soon
.
EDIT August 31st 2009: Blogged part 2.


