Developing for the Windows 7 Taskbar – Jump into Jump L

    Developing for the Windows 7 Taskbar – Jump into Jump L


    Posted: 25 Jun 2009
    This is the second post about the Taskbar Jump List in a series of Windows 7 Taskbar posts. In the previous post, Developing for the Windows 7 Taskbar – Jump into Jump Lists – Part 1, we introduced the elements that comprise the Taskbar Jump Lists: the destination (also referred to as “nouns”) and the Tasks (also referred to as “verbs”). As developer, you have a large amount of control over these elements. In this post, we walk through the different APIs that you can use when programming the Taskbar Jump Lists.

    Before we begin, there is one very important thing you need to know. “Items” in the Recent category, or in any other category (any destination), must have a registered file handler for your application in the registry. This doesn’t mean that your application must be the default handler for that specific file type, it just means that your application must have a registered handler for all the files that you want to be visible in the Jump List. Therefore, “items” can only be files. Remember, by clicking on one of the items in the Jump List, the OS executes the command associated with that file as it relates to your application. When you register a file handler, you also specify the application that handles this file, and you define how to pass the input parameter for the application. Another important note to remember: All the items (files) have to be local – that is, on the local hard drive, and accessible to your application. Therefore, we can say that each and every item among the Jump List destinations is an accessible, local file, with a file handler registered to your application.

    As we explain in the following section, once you have registered your file handlers, the OS actually helps you keep track of all your files. We will cover file handler registration in the next post.

    Step 1 – Use the Out-of-the-Box Windows Experience and Default Behavior

    By default, a Jump List contains a Recent category that is populated automatically for file-based applications through the SHAddToRecentDocs function. This function adds the used “item” (file) to the Shell's list of recently used documents. In addition to updating its list of recent documents, the Shell adds a shortcut to the user's Recent directory. The Windows 7 Taskbar uses that list and the Recent directory to populate the list of recent items in the Jump Lists.

    Windows can also do the work for you if your application's file type is registered. Anytime you double click on a file type with a registered handler, before Windows launches your application it automatically calls SHAddToRecentDocs on your application's behalf. This inserts the item in the Windows Recent list and eventually into the Jump List Recent Category. The same automatic behavior occurs when using the Windows Common File Dialog (CFD) to open files through our applications. Therefore, this is another good reason to use the CFD introduced in the Windows Vista timeframe, and it also plays a vital role regarding libraries, as we explained in the Light Up with Windows 7 Libraries post.

    Both of the above cases exploit default Windows behavior in cases where you have a registered handler and an Application ID by which the files are associated with Recent and Frequent lists. In both cases, Windows automatically inserts the items into the Jump Lists unless you specifically remove this functionality by using the COM API. Obviously, users also have the option to remove any items from their Jump Lists. By explicitly removing an item from the Jump List, you insert it into the Removed Items List, which we will discuss below.

    Step 2 – Create Your Own Category

    If the default Recent or Frequent categories do not meet your application's needs, it is time to create your own custom category. In order to do so, you need to use the ICustomDestinationList interface to create a custom Destination List.

    The ICustomDestinationList exposes methods that allow an application to provide a custom Jump List, including destinations and tasks, for display in the Taskbar. Here are the methods that we are using for the example below:


    • AppendCategory Defines a custom category and the destinations that it contains for inclusion in a custom Jump List
    • AppendKnownCategory Specifies that the Frequent or Recent category should be included in the Jump List
    • BeginList Initiates a building session for a custom Jump List
    • CommitList Declares that the Jump List initiated by a call to BeginList is complete and ready for display

    The following code snippet shows how to create a new custom list called “Custom Lists” and appends a few items to it:

    void CreateJumpList()
    {
    ICustomDestinationList *pcdl;
    HRESULT hr = CoCreateInstance(
    CLSID_DestinationList,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_PPV_ARGS(&pcdl));
    if (SUCCEEDED(hr))
    {
    //important to setup App Id for the Jump List
    hr = pcdl->SetAppID(c_szAppID);
    if (SUCCEEDED(hr))
    {
    UINT uMaxSlots;
    IObjectArray *poaRemoved;
    hr = pcdl->BeginList(
    &uMaxSlots,
    IID_PPV_ARGS(&poaRemoved));
    if (SUCCEEDED(hr))
    {
    hr = _AddCategoryToList(pcdl, poaRemoved);
    if (SUCCEEDED(hr))
    {
    pcdl->CommitList();
    }
    poaRemoved->Release();
    }
    }
    }
    }

    Here you see that we started with a standard COM initialization call. We call CoCreateInstance to initialize the ICustomDestinationList object (this is the joy of working with COM….). Next, we set the Application ID in order to allow you to start populating items to the list.

    The BeginList function initiated the build session for the custom Jump List. This function returns the maximum number of items that can fit in a given Jump List; the default is 10. You may note the Remove item parameter, IObjectArray *poaRemoved, that the BeginList() returned as an out parameter. This holds any specific items that the user removed from the Jump List in his current session. We discuss the Removed Items List later in this post.

    Next we called a helper function, _AddCategoryToList(), to do the actual work of adding items into the custom category.

    // This is the helper function that actually appends the items to a collection
    // object HRESULT _AddCategoryToList(ICustomDestinationList *pcdl,
    // IObjectArray *poaRemoved)
    {
    IObjectCollection *poc;
    HRESULT hr = CoCreateInstance
    (CLSID_EnumerableObjectCollection,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_PPV_ARGS(&poc));
    if (SUCCEEDED(hr))
    {
    for (UINT i = 0; i < ARRAYSIZE(c_rgpszFiles); i++)
    {
    IShellItem *psi;
    if (SUCCEEDED(SHCreateItemInKnownFolder(
    FOLDERID_Documents,
    KF_FLAG_DEFAULT,
    c_rgpszFiles[i],
    IID_PPV_ARGS(&psi)))
    )
    {
    if(!_IsItemInArray(psi, poaRemoved))
    {
    poc->AddObject(psi);
    }

    psi->Release();
    }
    }

    IObjectArray *poa;
    hr = poc->QueryInterface(IID_PPV_ARGS(&poa));
    if (SUCCEEDED(hr))
    {
    pcdl->AppendCategory(L"Custom category", poa);
    poa->Release();
    }
    poc->Release();
    }
    return hr;
    }
    Another new interface that we use is the IObjectCollection that represents a collection of objects that support IUnknown. To this collection we add IShellItems. Each item (file) that we added to the Jump List is of an IShellItem type. In the above code, we created a Shell item object for a single file that exists inside a known folder, Documents. However, before we actually added the new item to the collection, we needed to determine if the user had already removed it. If the user explicitly removed an item from the Jump List, that item will be in the Removed Items List (again associated with the AppID), and, as developers, we need to respect the user's requests and avoid adding that item to the Jump List. We already have the list of removed items, IObjectArray *poaRemoved, that we got when we called the BeginList(…) function when we initiated creation of a new list.

    At this stage, you have a collection of Shell items that the user expects to see in the Jump List. Next we added that collection to the ICustomDestinationList object and created a new category named “Custom category”, pcdl->AppendCategory (L"Custom category", poa);.

    So now you have successfully created a new category in the Taskbar called “Custom category” and populated it with four items. However, our work is not done yet. The final step in the CreateJumpList function is to call CommitList() to end the “transaction” that began with calling BeginList(). Only after our call to CommitList()arethe new category and new items displayed. Calling CommitList() causes the stored list of removed items to be cleared and a new Removed Items List to begin. The ICustomDestinationList interface provides a "transactional base" API.

    In order to ensure a positive end user experience, make sure that a safe copy of the new repopulated list is complete and ready for use, and that the only operation the Taskbar must perform is to switch the pointer to the new list. The end result looks like:



    Using the Windows API Code Pack we can write the same application using managed code.

    Once we are sure that we are using the same AppID with all the Taskbar elements, we can create an instance of the Taskbar Jump List for the button that we are working on, as shown in the following code snippet. This code snippet is part of the CTOR of the main application window:

    // Set the application specific id
    Taskbar.AppId = appId;
    // Retrieve the taskbar jump list
    jumpList = Taskbar.JumpList;
    category1 = new CustomCategory("Custom Category 1");
    category2 = new CustomCategory("Custom Category 2");
    // Add custom categories
    jumpList.CustomCategories.Add(category1);
    jumpList.CustomCategories.Add(category2);
    // Default values for jump lists
    comboBoxKnownCategoryType.SelectedItem = "Recent";
    Here you can see that we set the AppID using the AppId property and created an instance of the Taskbar Jump List using the Taskbar.JumpList static property. We also create two categories, named Custom Category 1 and Custom Category 2. Next, we add these categories to the Jump List custom categories container. Last we set the Known category of this Taskbar Jump List to Recent. This will automatically get populated as described above.

    After we set up the custom category, it is time to put some content in it. To do so, we just need to call the Add function to add a JumpListItem to the JumpListCollection. The JumpListItemCollection is a generic collection (of) holding IJumpListItem items. IJumpListItem item is basically some sort of wrapper for the native IShellItem.

    // Specify path for shell item
    string path = String.Format("{0}\\test{1}.txt",
    executableFolder,
    category1.JumpListItems.Count);
    // Add shell item to custom category
    category1.JumpListItems.Add(new JumpListItem(path));
    First, we need to construct a path to the file we want to include in the Jump List. Please remember that we can call the Add function only if this file is local and accessible to your user. The above code (along with a few other methods that we will describe in future posts), results in a Taskbar dialog that looks like:

    Finally, we need to call the Taskbar.JumpList.RefreshTaskbarList() Function. As with the native Jump List implementation, we need to “commit” the changes made to the Jump List. A closer look at this Refresh function (you have access to it in the Code Pack API) shows a call to the AppendCustomCategories function that appends any custom categories to the Taskbar button Jump List. Within this function, you can find a managed code implementation of the native code shown above. It includes a call to the AppendCateogry function that is a wrapper for the native AppendCategory function above.
    &#160;
    IObjectCollection categoryContent =
    (IObjectCollection)new CEnumerableObjectCollection();

    // Add each link's shell representation to the object array
    foreach (IJumpListItem link in category.JumpListItems)
    categoryContent.AddObject(link.GetShellRepresentation());

    // Add current category to destination list
    HRESULT hr = customDestinationList.AppendCategory(
    category.Name,
    (IObjectArray)categoryContent);

    &#160;
    As you can see, it is easy to opt into the Windows 7 Taskbar functionality. Windows automatically performs most of the work for you and, if you do need to create your own category, that is also very easy.

    In the next post we will describe how you can add new Tasks to the Jump List and how to register a file handler.


    More...
    z3r010's Avatar Posted By: z3r010
    25 Jun 2009



  1. Posts : 1,806
    Windows 7 Ultimate x32
       #1

    cool. one of you 'techy' guys needs to make a direct link to the forum
    complete with flashy button, and official icon. that'd be the cats arse.
    my luck i'd make some kind of computer explosion button.... click ..... ZTTTT (dead pc)
      My Computer

  2.    #2

    holo88 said:
    that'd be the cats arse
    I like that phrase , almost as much as the mutts nuts lol.

    I agree a custom button for the forum would be great. The article looks pretty cool but to be honest its way to complicated for me to grasp.
      My Computer


 

  Related Discussions
Our Sites
Site Links
About Us
Windows 7 Forums is an independent web site and has not been authorized, sponsored, or otherwise approved by Microsoft Corporation. "Windows 7" and related materials are trademarks of Microsoft Corp.

© Designer Media Ltd
All times are GMT -5. The time now is 19:45.
Find Us