Customizing Windows 7 Taskbar from WPF – Part 2 (Jumplist Custom Actions)

November 21, 2010

no comments

In my previous post I showed how to use a native resource in a .NET application and how to pick a custom icon for Jumplist Tasks.


In this post I would like to show how to activate custom actions from the Windows 7 Jumplist, exactly like Window Media Player and other applications do.


image


Programs designed for Windows 7 can take advantage of the taskbar features for quickly activating application’s common actions even though the application is minimized.


Actions could be added to both thumbnail toolbars and Jumplist.


Before adding actions to the Jumplist you should ask yourself few questions:



  1. Do users often need to start new tasks using your program?

  2. Do users often need to access recently or frequently used files, folders, links, or other resources?

  3. Do users often need quick access to a small number of your program’s commands while using other programs, even if your program isn’t running?

Other things you should consider:



  1. The Windows 7 Jumplist can be opened even though the application is not running – In such case you should execute the application if not running.

  2. It is not reasonable to have actions in the Jumplist related to single application instance and there are multiple instances running – Hence the application should be singleton.

Since Jumplist tasks can only be associated with executables, activating application’s actions is not directly possible.


To overcome this limitation you should make your application single-instance and pass arguments to it each time the user clicks on a Jumplist task.


Developing your application as a single instance and pass arguments to it is not a simple task at all, but cheer up, there is a very nice piece of code which does exactly what you need. This code can be found in the Microsoft’s Books.Show WPF Demo application I’ve been working on with my colleague, Arik Poznanski. You can also read more about it in Arik’s Blog (thanks Arik).


To turn your application into a single-instance, change the App build action to Page instead of ApplicationDefinition. Create a static Main method and implement the ISingleInstanceApp as follows:

public partial class App : Application, ISingleInstanceApp
{
    [
STAThread
]
   
private static void Main(string
[] args)
    {
       
if (SingleInstance<App>.InitializeAsFirstInstance(“Jumplist.App”
))
        {
           
var app = new App
();
            app.InitializeComponent();
           
app.Run();
        }
    }

   
bool ISingleInstanceApp.SignalExternalCommandLineArgs(IList<string
> args)
    {
       
return true;
    }   

}

Now that your application is single-instance:



  1. Create a Jumplist in the App.xaml with one task which has Title, Custom Icon (see prev post) and Description.

  2. Set the task ApplicationPath property with your application exe full path.

  3. Set the task Arguments property with a well-known string your application will parse as action. <JumpList.JumpList>
    <JumpList ShowRecentCategory=“True” 
              ShowFrequentCategory=“True”>
        <JumpTask Title=“Say Hello!”
      
                 
    Description=“Display Greeting Message”
      
                 
    ApplicationPath=“your-application-exe-full-path” 
                  Arguments=”SayHello /> 
        </JumpList>
    </JumpList.JumpList>

  4. Parse the arguments in the ISingleInstanceApp.SignalExternalCommandLineArgs method and activate the relevant action. This method is invoked when one instance of your application is already running and the user clicks on a task from the Jumplist.

    bool ISingleInstanceApp.SignalExternalCommandLineArgs(IList<string> args)
    {
       
    if
    (args.Count > 1)
        {
            ProcessAction(args[1]);                
        }

       
    return true
    ;
    }

    private void ProcessAction(string actionString)
    {
        Dispatcher.BeginInvoke(() =>
        {
           
    switch
    (actionString)
            {
               
    case ApplicationActions
    .SayHello:
                   
    MessageBox.Show(“Greetings!”
    );
                   
    break;
            }
        });
    }

  5. You should also be aware that the user may click on the Jumplist while your application isn’t running. To handle this case, override the Application.OnStartup method and check the arguments. You’ll have the action string as first argument in case that the user activates a task while no application is running.
protected override void OnStartup(StartupEventArgs e)
{           
   
base
.OnStartup(e);

   
if (e.Args.Length > 0)
    {
        Dispatcher.BeginInvoke(() => ProcessAction(e.Args[0]));
    }
}
image

Note: The dispatcher call is to ensure that the MainWindow is created and initialized, also if you’ve implemented MVVM you may want one or more view-model to handle the command, so you have to be sure that the relevant view-model is ready to act.


Of course you should handle other command line arguments. This topic is out of the scope of this post, but you can find information about it here.


Feel free to download my code from here (don’t forget updating the JumpTask to use your application exe full path. I’ll provide better solution to this in my next post).


In the next post I’ll show how to handle Jumplist properly with MVVM pattern, using markup extensions, commands and pub-sub events.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*