Developing for the Windows 7 Taskbar – Jump into Jump L

    Developing for the Windows 7 Taskbar – Jump into Jump L


    Posted: 02 Jul 2009
    So far, you have seen how you can opt into the Windows 7 Taskbar Jump List experience by creating a Jump List for your application (in the Developing for the Windows 7 Taskbar – Jump into Jump Lists – Part 2 post.) You have also seen the Windows 7 default support for listing “Recent” or “Frequent” destinations as well as how to create your own custom categories. In this post, we will explore more of the Jump List features and discover how easy it is to add Tasks to your application's Jump List.

    User tasks are customized tasks that get their own Tasks category. As a developer, you can set the title of the displayed task, the icon on the left and, more important, and the “application” that is launched once you activate this task. You can view user’s tasks as shortcuts to the functionality our applications can provide. As you might remember, user tasks are the verbs in our vocabulary; for example, Windows Media Player provides a “Resume last playlist” task and Sticky Notes provides a “New note” task.

    A user task is usually an IShellLink object that launches any given application (your application or any other one you choose) with specific command line parameters. While you cannot categorize tasks, you can separate them using a special separator object. Here’s an example of a Jump List that uses a separator to split three tasks into a group of two plus an additional task:



    So what does it take to add tasks to a Jump List? Well, not that much. Basically it is a single call to the AddUserTasks function in an interface that we are already familiar with, the ICustomDestinationList (ICustomDestinationList::AddUserTasks(IObjectArray) Method). Looking at the code, you will see a single line of code, hr = pcdl->AddUserTasks(poa);.However, as always, someone needs to create and build that poa, IObjectArray, and parameter and fill it with relevant information. Let’s review that process now.

    We are going to create a collection of IShellLinks. This collection will be later cast to the required IObjectArray parameter. The following code is the beginning of that process.

    IObjectCollection *poc;
    HRESULT hr = CoCreateInstance(
    D_EnumerableObjectCollection, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&poc));
    if (SUCCEEDED(hr))
    {
    IShellLink * psl;
    hr = _CreateShellLink(L"/Task1", L"Task 1", &psl);
    if (SUCCEEDED(hr))
    {
    hr = poc->AddObject(psl);
    psl->Release();
    }
    }
    Here you can see that we used COM (again) and CoCreate and IObjectCollection, poc. Next, we call to a helper function called CreateShellLink that receives three parameters:

    • The first parameter is the command line argument to the task
    • The second parameter is the title that will be displayed
    • The last parameter is a pointer to IShellLink
    The object is then filed according to the relevant information.

    Last, we add the recently created IShellLink to the object collection. You may ask yourself where the parameter that provides the path to the executable that we plan to launch is. Well that is a good question. For simplicity, we have hard-coded that information as shown in the following code snippet:

    if (SUCCEEDED(hr))
    {
    hr = _CreateShellLink2(
    L"C:\\Users\\\\Documents\\new text file.txt",
    L"NotePad",
    &psl);

    if (SUCCEEDED(hr))
    {
    hr = poc->AddObject(psl);
    psl->Release();
    }
    }
    Here you can see we call to a hard-coded _CreateShellLink2 function. This receives a path to a text file as one of its parameters and, as you can see, we are launching Notepad.

    Here is the code for the CreateShellLink2 function:

    HRESULT _CreateShellLink2(
    PCWSTR pszArguments, PCWSTR pszTitle,
    IShellLink **ppsl)
    {
    IShellLink *psl;
    HRESULT hr = CoCreateInstance(
    CLSID_ShellLink,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_PPV_ARGS(&psl));
    if (SUCCEEDED(hr))
    {
    hr = psl->SetPath(c_szNotePadExecPath);
    if (SUCCEEDED(hr))
    {
    hr = psl->SetArguments(pszArguments);
    if (SUCCEEDED(hr))
    {
    // The title property is required on Jump List items
    // provided as an IShellLink instance. This value is used
    // as the display name in the Jump List.
    IPropertyStore *pps;
    hr = psl->QueryInterface(IID_PPV_ARGS(&pps));
    if (SUCCEEDED(hr))
    {
    PROPVARIANT propvar;
    hr = InitPropVariantFromString(pszTitle, &propvar);
    if (SUCCEEDED(hr))
    {
    hr = pps->SetValue(PKEY_Title, propvar);
    if (SUCCEEDED(hr))
    {
    hr = pps->Commit();
    if (SUCCEEDED(hr))
    {
    hr = psl->QueryInterface
    (IID_PPV_ARGS(ppsl));
    }
    }
    PropVariantClear(&propvar);
    }
    pps->Release();
    }
    }
    }
    else
    {
    hr = HRESULT_FROM_WIN32(GetLastError());
    }
    psl->Release();
    }
    return hr;
    }
    To start with, again we need to use COM and CoCreate to create an IShellLink COM object. A quick look at the SDK reveals that the IShellLink object has many functions. Here are few that we will use:

    • GetPath Gets the path and file name of a Shell link object, that is the path to the executable
    • GetShowCmd Gets the show command for a Shell link object, the executable name
    • SetArguments Sets the command-line arguments for a Shell link object
    • SetDescription Sets the description for a Shell link object; the description can be any application-defined string
    • SetIconLocation Sets the location (path and index) of the icon for a Shell link object SetPath Sets the path and file name of a Shell link object
    • SetWorkingDirectory Sets the name of the working directory for a Shell link object
    As you can see, for each parameter we must get and set appropriate methods. There are additional parameters; take a look at the SDK - IShellLink if you want to learn more.

    In the above example, we set the path to Notepad (by default in the Windows 7 installation, c:\windows\notepad.exe). We also passed a hard-coded (not a good practice) command line argument pointing to a text file in my private document folder (C:\Users\\Documents\new text file.txt.) The rest of the code sets the title property that is required on Jump List items.

    We call the CreateShellLink2 and CreateShellLink a few more times to add all three shortcuts as shown in the above screen capture.

    Now let’s add a separator.





    To add a separator to our Task List, we need to create an IShellLink, and set the PKEY_AppUserModel_IsDestListSeparator property using the COM property variant as shown in the following code snippet:

    // The Tasks category of Jump Lists supports separator items.
    // These are simply IShellLink instances that have the
    // PKEY_AppUserModel_IsDestListSeparator property set to TRUE.
    // All other values are ignored when this property is set.
    HRESULT _CreateSeparatorLink(IShellLink **ppsl)
    {
    IPropertyStore *pps;
    HRESULT hr = CoCreateInstance(
    CLSID_ShellLink,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_PPV_ARGS(&pps));
    if (SUCCEEDED(hr))
    {
    PROPVARIANT propvar;
    hr = InitPropVariantFromBoolean(TRUE, &propvar);
    if (SUCCEEDED(hr))
    {
    hr = pps->SetValue(PKEY_AppUserModel_IsDestListSeparator, propvar);
    if (SUCCEEDED(hr))
    {
    hr = pps->Commit();
    if (SUCCEEDED(hr))
    {
    hr = pps->QueryInterface(IID_PPV_ARGS(ppsl));
    }
    }
    PropVariantClear(&propvar);
    }
    pps->Release();
    }
    return hr;
    }

    Here you can see that we used CoCreate to create an IShellLink object. Next, we set a PROPVARIANT, propvar, to true and set the IShellLink object PKEY_AppUserModel_IsDestListSeparator property to true. This will instruct the OS to render this IShellLink as a separator and not just as regular IShellLink.

    OK, that was long. Now let’s look at the short version, using .NET. For that we are going to use the Windows API Code pack for the .NET Framework.

    As we can expect from .NET, we get abstraction from most of the “COM code behind” that is required. The Microsoft.WindowsAPICodePack.Shell.Taskbar namespace includes a JumpListLink object that extends the ShellLink object and implements IJumpListTasks.

    The JumpList class contains the UserTasks collection of IJumpListTasks to which you can simple add new JumpListLink objects as shown in the following code snippet:

    // Path to Windows system folder
    string systemFolder =
    Environment.GetFolderPath(Environment.SpecialFolder.System);

    jumpList.UserTasks.Add(new JumpListLink
    {
    Title = "Open Notepad",
    Path = Path.Combine(systemFolder, "notepad.exe"),
    IconReference = new IconReference(
    (systemFolder, "notepad.exe"), 0)
    });
    Using the C# 3.0 syntax, we initialize a new JumpListLink object and add it to the UserTasks collection. As you can see, the managed code JumpListLink has very similar properties to the native one (which makes perfect sense). We also added an icon to the Notepad shortcut to the above code, but didn't provide any command line parameters.

    You want to add a separator? Well, that is also very easy: just add a JumpListSeperator object to the UserTasks collection.

    jumpList.UserTasks.Add(new JumpListSeparator());
    Please note that, as always, when working with the Windows Code pack API Taskbar, you have to call the “refresh” function in order to commit the changes, as we explained in the previous post.
    Taskbar.JumpList.RefreshTaskbarList();
    After the refresh, the Jump List looks as follows:





    I’ve compiled a version of a native example from the Windows 7 SDK. You can get a copy of that code from here

    You can download the Windows API Code Pack that includes the manage code example we used in this post.

    This concludes our Jump List discussion. Our next Taskbar topic is Icon Overlay.


    More...
    z3r010's Avatar Posted By: z3r010
    02 Jul 2009



  1. Posts : 488
    Win 7 Pro x64 x 3, Win 7 Pro x86, Ubuntu 9.04
       #1

    I've already started using jumplists in my apps... I've been working on getting firefox to work like IE with it's jump lists and its thumbnails etc...
      My Computer


  2. Posts : 445
    Vista Ult 64bit - Windows 7 Ult 7264 64bit
       #2

    Hmmm..very interesting. I'll have to read up more on this bit of coding and see if I can find a use for my needs.

    @fakeasdf - Personally I find FF to be slow & bloated lately, have you checked out the new Opera lately? It takes code injection well and you just may find yourself really liking it over FF soon...
      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 13:58.
Find Us