Windows 7: Jump Lists
- Posted: Dec 09, 2009 at 1:59 PM
- 5,015 Views
- 13 Comments
Loading User Information from Channel 9
Something went wrong getting user information from Channel 9
Loading User Information from MSDN
Something went wrong getting user information from MSDN
Loading Visual Studio Achievements
Something went wrong getting the Visual Studio Achievements
In this article, learn how to provide quick access to links and actions in your Windows 7 application by creating a Jump List.
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.
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.
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 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:
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:
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" });
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.
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.
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.
From Solution Explorer, right-click the setup project, then click the View | File Types menu command.
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.
The file type should appear like the following in the File Types tab:
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.
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.
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.
Follow the Discussion
Oops, something didn't work.
What does this mean?
Following an item on Channel 9 allows you to watch for new content and comments that you are interested in. You need to be signed in to Channel 9 to use this feature.What does this mean?
Following an item on Channel 9 allows you to watch for new content and comments that you are interested in and view them all on your notifications page.sign up for email notifications?
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
Thanks very helpfull.
One question, how would i get the recent list to display visited websites "urls", like IE8 jumplist.?
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
Ok, forgot to set working directories, that solved the issue with the xml.
Thanks
@M.des YourJumpListObject.AddUserTasks(New JumpListSeparator())
This was covered in the article
How to add a line with VB.net?
How do you create a setup project? Visual Studio 2010 has no such template.
@Anonymous in Visual Studio 2010, Other Project Types -> Setup and Deployment -> and there are multiple types you can pick from there
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 .
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?
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