Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Windows 7: Jump Lists

In this article, learn how to provide quick access to links and actions in your Windows 7 application by creating a Jump List.

Introduction

Windows 7 includes a wealth of new features for developers to take advantage of.  This includes better rendering subsystems, new sensor and location API's, file libraries, federated search, and of course, the improved taskbar.  My last article discussed the taskbar's ability to show custom previews and toolbar icons.  This article focuses on Jump Lists - the replacement for notification area context menus.

To get started, download Visual Studio 2008 Express Edition or higher (C# or VB).  Or, just go for Visual Studio 2010 Beta 2 - it's available now and well worth the download.  All Express editions are free, and either 2008 or 2010 versions will work fine with this article's accompanying code.

What's a Jump List?

Jump Lists are a new concept in Windows 7 that allow developers to provide shortcuts for users right from their icon's context menu in the taskbar or Start menu.  The shortcuts could be simple links to the documents folder or a library for a given application, or links back to the same application with a parameter passed to cause something to happen.

You can use this method in Live Messenger to change online status, display the new message window, or open web pages relating to the application.  In the end, all of these are shortcuts.  Shortcuts to URL's, or shortcuts back to the executable with an argument that causes some change to occur.

Windows API Code Pack

The Windows API Code Pack lets you take advantage of specific features of Windows Vista and Windows 7 that aren't available across the general framework, as well as native features that don't make sense in the common CLR used across all the supported configurations. Much of it consists of interop wrappers.

With the Code Pack, you get access to the new taskbar, Direct2D, DirectWrite, shell properties, Jump Lists, and more. The download also includes numerous sample code projects to get you started, so there's no excuse for avoiding new features!

Adding a Jump List

Adding a Jump List is easy.  After you create the list itself, add items (shortcuts to files or folders, and tasks) to it.  Then, you can choose how a user's recent or frequently used documents show up.  Windows manages the user documents list, which relieves you of some work.

It's important to note that in order to make a change to the list, you have to recreate the entire thing.  In other words, you'll replace the old list with a new one, rather than updating it.

Here's how the process works:

First, add the two required references from the Windows API Code Pack.  You can either build a project and reference the DLL's, or directly add projects to your solution:

Windows API Code Pack references

For convenience, you can add the namespaces to your using block to shorten typing later:

Visual Basic

Imports Microsoft.WindowsAPICodePack.Taskbar
Imports Microsoft.WindowsAPICodePack.Shell

Visual C#

using Microsoft.WindowsAPICodePack.Taskbar;
using Microsoft.WindowsAPICodePack.Shell;

 

The Microsoft.WindowsAPICodePack.Taskbar.JumpList class is where most of the action is.  There's a static factory method, CreateJumpList, to create the list.  Always start by calling this method, even if the application has created a Jump List in the past.

Visual Basic

Private Sub CreateJumpList()
    Dim jl As JumpList = JumpList.CreateJumpList()

Visual C#

private void CreateJumpList()
{
    JumpList jl = JumpList.CreateJumpList();

 

Next, you have several options, depending on what you need in the list.  The most basic group is the list of files.  You can choose to show Recent files, Frequent files, or neither-but you can't have both.  If you don't make a choice here, you'll get Recent files automatically, as long as you have a registered file type.

Visual Basic

' Show user files: Recent, Frequent, or None
jl.KnownCategoryToDisplay = JumpListKnownCategoryType.Recent

Visual C#

// Show user files: Recent, Frequent, or None
jl.KnownCategoryToDisplay = JumpListKnownCategoryType.Recent;

Now you can add one or more custom categories of items.  These are either folders or files.  There are two very important rules:

  1. The files/folders must exist!  If necessary, check the path before adding the JumpListItem or you'll have a crash. 
  2. The files you add have to be of a type registered for your application, or you'll crash. Even worse: the exception won't occur on the line where you add it, but rather when you're done setting it up and try to refresh the list.

I've commented out the last item here, but you would use a JumpListItem for actual file system files, and JumpListLink objects for non-filesystem references.  Again, don't add a JumpListItem unless you know that it exists and that you're registered to handle it.

Visual Basic

' Add my own links (nouns)
Dim catActions As New JumpListCustomCategory("Destinations")

catActions.AddJumpListItems(
    New JumpListLink(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "My Pictures"), _
    New JumpListLink("http://blogs.msdn.com/coding4fun", "Visit Coding4Fun"), _
    New JumpListLink("http://code.msdn.microsoft.com/WindowsAPICodePack", "Windows API Code Pack"))
    'new JumpListItem(@"c:\Test1.c4f")

jl.AddCustomCategories(catActions)

Visual C#

// Add my own links (nouns)
JumpListCustomCategory catActions = new JumpListCustomCategory("Destinations");
catActions.AddJumpListItems(
    new JumpListLink(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "My Pictures"),
    new JumpListLink("http://blogs.msdn.com/coding4fun", "Visit Coding4Fun"),
    new JumpListLink("http://code.msdn.microsoft.com/WindowsAPICodePack", "Windows API Code Pack")
    //new JumpListItem(@"c:\Test1.c4f")
    );

jl.AddCustomCategories( catActions);

You can add one or more tasks as  links to system executables by using the AddUserTasks method of the JumpList object.  Either create multiple objects and add them as a variable argument list, or add them one at a time, as I have here.

Visual Basic

' Add our user tasks (verbs)
jl.AddUserTasks(New JumpListLink(Path.Combine(systemFolder, "notepad.exe"), "Open Notepad") _
    With {.IconReference = New IconReference(Path.Combine(systemFolder, "notepad.exe"), 0)})

Visual C#

jl.AddUserTasks(new JumpListLink(Path.Combine(systemFolder, "notepad.exe"), "Open Notepad")
{
    IconReference = new IconReference(Path.Combine(systemFolder, "notepad.exe"), 0)
});

The IconReference property sets a pointer to the icon by referencing a DLL or EXE and then an index.  Specifying an EXE with "0" is a good way to get the default icon for an executable that you are linking to.

You can add a separator to the list whenever you need to.  The JumpListSeparator class represents a separator and can be added using the AddUserTasks call.

Visual Basic

jl.AddUserTasks(New JumpListSeparator())

Visual C#

jl.AddUserTasks(new JumpListSeparator());

The final links in our Jump List link back to our own executable. This is the most common use of Jump Lists.  Just having a Recent/Frequent list is nice, but being able to trigger actions on the program itself-even when it's not started-is really handy.  It's almost like a menu of command line options!

Commands in the list that invoke actions on the application itself involve calling the same application with different arguments.  Remember that this isn't a true menu; you won't receive a Click event.  Instead, you need to deal with an argument that's passed to you, even if you're already running.

Remember that the first argument on the command line is always the fully-qualified location to the running executable.  The Arguments property lets you specify command line arguments that users don't directly see.  For this sample application, I've defined three dummy arguments.  If one of these is passed in, the application changes the background color of a label and indicates which argument it was.

Visual Basic

jl.AddUserTasks(New JumpListLink(Assembly.GetEntryAssembly().Location, "Action 1 (Green)") _
    With {.Arguments = "-1", .IconReference = New IconReference(Assembly.GetEntryAssembly().Location, 0)})

Visual C#

jl.AddUserTasks(new JumpListLink(Assembly.GetEntryAssembly().Location, "Action 1 (Green)")
{
    IconReference = new IconReference(Assembly.GetEntryAssembly().Location, 0),
    Arguments = "-1"
});

Sample JumpList

Invoking Self Actions

Windows Live Messenger uses Jump List actions for setting its own available status, and Windows Media Player has Jump List actions for skipping tracks or stopping.  Likewise, you can add tasks that invoke actions on the same executable.  If the application isn't running (remember that the Jump List is still available), this will cause it to be launched with the right argument.  That's no problem.  What if it's already running though?

The key is to find a way to pass messages between running instances.  When the application starts up, check to see if another instance is running by using a Mutex (see Program.cs).  If not, just use the arguments directly.  If it is running, send the information about the parameter to the other instance and then quit.  You could use temporary files, shared registry keys, or memory-mapped files.  I find it easiest to use window messages.

You can find the code to create custom message ID's, to find the right window, and to send the message in my WindowsMessageHelper class.

From the main window code, override the WndProc method.  This is the message loop for everything: mouse events, key events, window closing, and much more.  Ensure that the message is something you need; otherwise pass it on to the underlying handler.

If the application is already running, post a message.  If not, start as usual and watch your message queue.  If you see a message of interest, take some action (in this case, just showing a message and changing a color). 

The only other tricky thing to remember, is that you might startup as the only instance, and also have a parameter.  For example, if the user clicked a task on the Jump List but the application isn't running.  I take the easy way out and check for parameters after fully starting up and then post to my own queue if needed!  That simplifies some of the logic anyway.

If you don't mind using the Microsoft.VisualBasic.ApplicationServices namespace from C#, then you can take advantage of the VB SingleInstance application mode.  This removes the need for any explicit mutex, interop, or message passing.  You can find some great information about this on Jocelyn Villaraza's excellent blog post.

Registering a File Type

Remember: unless you're registered as a file handler for the type, you can't show recent or frequent files or point to individual files.  Register to be a file handler by creating a registry write operation to a key under HKEY_CLASSES. 

The problem is, you can't write to the HKEY_CLASSES branch of the registry without proper permissions.  By default, permission is only granted to the Administrators group.  You really don't want to require that your application run under administrative privileges-that would be so Windows XP!

There are two alternatives: you could create a second application that can run elevated in order to perform the registration.  This is how the samples do it with the Windows API Code Pack. A better method is to create a custom installer for the project and perform the association there.  Installers always require administrative rights, and they only need to run once.

Creating the Installer

To create the installer, first add a setup project to your solution, following the usual steps. Then, from the Project types list, click Other Project Types | Setup and Deployment.  In the Templates list, click Setup Project. Give it a name, then add it.

New project types

From Solution Explorer, right-click the setup project, then click the View | File Types menu command.

View File Types

From the File Types list, right-click File Types on Target Machine, and then click Add File Type.  Fill out the properties to name the file type and provide the extension.  For Command, be sure to set it to the Primary output of the main project. 

File type properties

The file type should appear like the following in the File Types tab:

File Types list

Now you have a registered file type.  You still need to modify your setup project to copy the primary output (the EXE) to Program Files and customize any other properties in the setup project, but these are the special steps for file types.  If in doubt, take a look at sample code to see how the Setup project is configured.

Conclusion

Working with the Windows API Code Pack makes it much easier to customize the taskbar and add Jump Lists, and gives you a great experience that really integrates well with the system.  Download Visual Studio Express, grab the Windows API Code Pack, and start digging in.

The new features won't work on machines prior to Windows 7, so be sure to check that they're supported.

Tags:

Follow the Discussion

  • Walker (Windows Outreach Team)Walker (Windows Outreach Team)

    Thanks Arian for this helpful tool! If readers are at all interested in the development history of Jump Lists, be sure to check out this interview with their inventor, Rebecca Deutsch: http://www.microsoft.com/presspass/features/2010/jan10/01-04Win7JumpList.mspx?rss_fdn=TopStories">http://www.microsoft.com/presspass/features/2010/jan10/01-04Win7JumpList.mspx?rss_fdn=Top Stories

    Cheers!

    Walker

    Windows Outreach Team

  • KevinKevin

    Thanks very helpfull.

    One question, how would i get the recent list to display visited websites "urls", like IE8 jumplist.?

  • KevinKevin

    OK this is how i get the history to show.

    private void ReportUsage()

           {

               XmlDocument myXml = new XmlDocument();

               myXml.Load(historyXml);

               string list = historyXml;

               jumpList.ClearAllUserTasks();

               foreach (XmlElement el in myXml.DocumentElement.ChildNodes)

               {

                   string s = el.GetAttribute("url");

                   JumpListLink jll = new JumpListLink(Assembly.GetEntryAssembly().Location, s);

                   jll.IconReference = new IconReference(Path.Combine("C:\\Program Files\\ACS Digital Media\\TOC WPF Browser\\Icon1.ico"), 0);

                   jll.Arguments = el.GetAttribute("url");

                   jumpList.AddUserTasks(jll);

               }

               jumpList.Refresh();

           }

    Now another question which has me stumped.

    i want the program to launch from the taskbar with the same parameters as it does from the jumplist.

    I'm using xml to store Favorites and history, if i launch from the taskbar it uses the xml's in the program folder, however if i launch from the jumplist it uses xml's which have been placed in the System32 folder.

    Anyone know how to fix this.?

    Thanks

  • KevinKevin

    Ok, forgot to set working directories, that solved the issue with the xml.

    Thanks

  • Clint RutkasClint I'm a "developer"

    @M.des YourJumpListObject.AddUserTasks(New JumpListSeparator())

    This was covered in the article Smiley

  • M.desM.des

    How to add a line with VB.net?

  • AnonymousAnonymous

    How do you create a setup project? Visual Studio 2010 has no such template.

  • Clint RutkasClint I'm a "developer"

    @Anonymous in Visual Studio 2010, Other Project Types -> Setup and Deployment -> and there are multiple types you can pick from there

  • cheap fashion clothingcheap fashion clothing

    Shop Designer clothing for men’s and women’s. Large collection of discount clothing such as Burberry Womem Coats, Football Club Suits,brand underwear, Ed hardy Men Jackets and other cheap fashion clothing .

  • NicolasNicolas

    It's all fun and games, but how the heck are we supposed to install that pack? There are virtually no instructions and everything starts from step 11. I'd love to use these shiny features, if I only knew how.

  • Here is a Jumplist question I cannot find the answer anywhere:

    My app is VoIP app so I'd like to have a jumplist that has recent calls and frequent calls, or for simplicity it could be tasks.  A "normal" jumplist basically launches an app, in the example below it's a notepad:

    _jumpListManager.AddUserTask(new ShellLink
                {
                    Path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "notepad.exe"),
                    Title = "Launch Notepad",
                    IconLocation = shell32DllPath,
                    IconIndex = 14
                });

    In my particular case my app is not executable - it is an Outlook Add-In, so I cannot try to start Outlook again with some kind of parameter - it will not be passed to my add-in by Outlook.

    So I either need to write my own little helper app that accepts parameters or use some kind of trick (later about it). The little app would be windowless (but not the service) and carries its own complications, like communicating with my Outlook Add-In securely - using named pipes or similar opens quite a security hole in Outlook - and also seems too laboreous.... The "trick" solution is to use "regedit /s filename.reg" that will get my data into the registry from the reg file that my Outlook Add-in creates, while my add-in will be watching specific registry key. For the latter I will get UAC prompts for every jumplist click (and for now I cannot find how to over this without elevating entire outlook or disabling UAC - not something I want to do... So, basically my question is: is there any way to subscribe to Jumplist_Clicked event (or appropriate event) and get the event plus data in my Outlook Add-In?

  • AlQAlQ

    I can't find setup project anywhere, and the "other types" category doesn't exist. Where is the setup project in visual c# 2010?

    Oh, I am using the express version, I hope that isn't a problem.

  • A code sample would be a great addition.

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.