Custom Destinations
If the default Recent and Frequent destination categories provided by the Windows 7 Shell are
not enough for your application, you’ll want to create custom categories and store your
destinations within them. As we saw before, an e-mail application might want to use Inbox
and Follow-up categories, a Web browser might want to use a Favorites category, and so on.
Most destinations are nouns, and in the Windows 7 Shell world nouns are usually represented
by IShellItem objects, although IShellLink objects can be used as well.
Therefore, to create
custom destination categories, you first need to create custom destinations namely, their
IShellItem or IShellLink representations. If you place shell items in the Jump List, clicking them
opens your application (as a registered file handler for these shell items). If you place shell
links in the Jump List, they can point to arbitrary locations and arbitrary applications might be
used to open them. However, users will expect your application to be launched as a result of
clicking on an item in your application’s Jump List.
More Info For more information on the Windows 7 Shell object hierarchy, including IShellItem and
IShellLink. In native code, obtaining a
shell item usually involves calls to APIs such as SHCreateItemFromParsingName, whereas creating a
shell link involves co-creating CLSID_ShellLink and then setting the properties of the resulting
object. In managed code, the Windows 7 API Code Pack provides the JumpListItem and JumpListLink
classes for working with shell items and shell links.
Before populating your Jump List with custom destinations, there are two things to bear
in mind:
- There is a limited amount of screen state for your custom categories and items. You can
retrieve the maximum amount of items that can be placed in the Jump List by using the
pcMaxSlots parameter of the ICustomDestinationList::BeginList method or its managed
equivalent, JumpList.MaxSlotsInList, from the Windows 7 API Code Pack. Placing more items
on the screen than is allowed will not result in an error extraneous items will be
truncated, top to bottom.
- The Jump List belongs to the user and not to the application, which means the user can
choose to remove items from the Jump List even if you carefully placed them in specific
destination categories. When your application re-populates the Jump List for any reason,
it must remember the user’s choices and refrain from re-adding items that the user
removed earlier. Attempting to add an item that the user removed after the last listbuilding
transaction causes an exception.
Items Removed by the User
If your application displays Jump List items that are of no interest to the user, the user
can choose to remove them from the list. Your application cannot add items that were
previously removed by the user back to the Jump List doing so causes an exception
when the Jump List is constructed. The following screen shot shows how the user can
remove an item from a custom destination category displayed in an application’s
jump list:

The ICustomDestinationList::BeginList method provides you with an opportunity to
discover that the user removed items from the Jump List.
The ppv parameter of this
method will contain a collection (typically IObjectArray) of removed items IShellItem
and IShellLink objects. It’s also possible to call the
ICustomDestinationList::GetRemovedDestinations method directly to retrieve the list of
removed items without initiating a list-building transaction.
The managed equivalent for determining that items were removed from the Jump List is
the JumpList.RemovedDestinations property of the Windows 7 API Code Pack, which
proactively discovers removed items. Fortunately, the Windows 7 API Code Pack
automatically deletes removed items from the custom categories provided by the
application to ensure that items removed by the user are not re-added to the
application’s Jump List.
Working with custom destinations requires the ICustomDestinationList interface, which is
obtained by co-creating the CLSID_DestinationList COM object. If your application uses an
explicit application ID, you must use the ICustomDestinationList::SetAppID method before
using the resulting object.
As always, the managed Windows 7 API Code Pack streamlines this
work for you custom categories can be added using the JumpList.AddCustomCategories
method, and the application ID is automatically propagated from the
TaskbarManager.Instance.ApplicationID property.
A list-building transaction begins with a call to the ICustomDestinationList::BeginList method.
Subsequent method calls will not be applied to the actual Jump List until the CommitList
method is called to commit the changes, or until the AbortList method is called to roll back
the work. The managed wrapper does not require multiple steps it refreshes the Jump List
when changes are made to the underlying model and the JumpList.
Refresh method is called.
To construct the Jump List categories, a two-step approach is required. First, you construct a
collection (usually IObjectCollection) of custom destinations (IShellItem or IShellLink objects)
that belong to a category or, in managed code, create a JumpListCustomCategory object
and add JumpListItem and JumpListLink objects to it. Next, you call the
ICustomDestinationList::AppendCategory method to append the entire category to the list
or, in managed code, pass the JumpListCustomCategory object to the
JumpList.AddCustomCategories method.
The following code snippet, which displays both the native and managed code, shows how to
construct a Jump List with one custom category:
//C++:
ICustomDestinationList* pJumpList = NULL;
if (FAILED(CoCreateInstance(
CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pJumpList))))
goto Cleanup;
if (FAILED(pJumpList->SetAppID(L"Microsoft.Samples.MyApplication")))
goto Cleanup;
UINT uMaxSlots;
IObjectArray* pRemoved;
if (FAILED(pJumpList->BeginList(&uMaxSlots, IID_PPV_ARGS(&pRemoved))))
goto Cleanup;
IObjectCollection* pContents = NULL;
if (FAILED(CoCreateInstance(
CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pContents))))
goto Cleanup;
IShellItem* pItem = NULL;
if (FAILED(SHCreateItemInKnownFolder(
FOLDERID_Documents, KF_FLAG_DEFAULT, L"MyFile.txt", IID_PPV_ARGS(&pItem))))
goto Cleanup;
if (FAILED(pContents->AddObject(pItem)))
goto Cleanup;
IObjectArray* pContentsArr = NULL;
if (FAILED(pContents->QueryInterface(IID_PPV_ARGS(&pContentsArr))))
goto Cleanup;
if (FAILED(pJumpList->AppendCategory(L"My Category", pContentsArr)))
goto Cleanup;
pJumpList->CommitList();
Cleanup:
if (pContentsArr != NULL)
pContentsArr->Release();
if (pItem != NULL)
pItem->Release();
if (pContents != NULL)
pContents->Release();
if (pJumpList != NULL)
pJumpList->Release();
//C#:
JumpList jumpList = JumpList.CreateJumpList();
JumpListCustomCategory category = new JumpListCustomCategory("My Category");
category.AddJumpListItems(new JumpListItem(Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyFile.ext")));
jumpList.AddCustomCategories (category);
jumpList.Refresh();
Clearing the Jump List
If at any time you want to clear the Jump List, you can use the DeleteList method of the
ICustomDestinationList interface. In managed code, you can create an empty JumpList
instance and then call its Refresh method.
You should not clear the application Jump List when your application starts or worse,
during normal application execution. Users rely on the contents of the Jump List to
remain stable and like to retain the same categorized destinations and tasks across
multiple uses of an application. The reasonable use case for clearing the application’s
Jump List is when your application is uninstalled, or when the user explicitly asks to do
so for example, using a Clear History command in a Web browser. |