Can Of Code

How to add JumpLists to a C# Application

I yesterday thought that i would have a go at adding jumpLists to a c# application, i thought it should be rather simple perhaps all i would need to do is drag a component into the Visual Studio Designer and then i would be done. Well i was wrong…

For all those who don’t have a clue what JumpLists are, i shall explain. JumpLists where introduced in Windows 7.  A JumpList is a menu that appears when you right click the application icon in the taskbar. The image  below shows a JumpList in action.

JumpList in action

The way i use the JumpList in this tutorial is a simplified approach to the Single Instance taskbar tutorial that is explained here.

To add this functionality there are two real steps,

– Adding the JumpList (easy bit)

– Getting it to do something when the user clicks an item (hard bit)

 

Before we start

The JumpList functionality is not included in the .NET framework which i so naively thought it would be. So the first step we need to take is to download the Windows API code pack  which you can do here.

Once you have downloaded the API your need to add a reference to the Microsoft.WindowsAPICodePack.shell.dll that comes in the API.

We should also add a using to the top of our code:

using Microsoft.WindowsAPICodePack.Taskbar;

Adding the JumpList

Adding the JumpList to the application is pretty simple. The first issue your faced with is where to put the code, the code wont work in the forms constructor so to overcome this in the simplest way possible i have put the code in a form event called Form.Shown.

      private void Form1_Shown(Object sender, EventArgs e)
        {
            // get where the app is running from
            string cmdPath = Assembly.GetEntryAssembly().Location;

            // create a jump list
            JumpList jumpList = JumpList.CreateJumpList();

            JumpListCustomCategory category = new JumpListCustomCategory("Food");
            category.AddJumpListItems(
                new JumpListLink(cmdPath, "Crabs") { Arguments = "Crabs" },
                new JumpListLink(cmdPath, "Prawns") { Arguments = "Prawns" },
                new JumpListLink(cmdPath, "Shrimps") { Arguments = "Shrimps" });
            jumpList.AddCustomCategories(category);

            jumpList.Refresh();
        }

First of all i don’t check that the user is running windows 7 which will cause exceptions with non Windows 7 users so i would recommend adding a check before running this code.

The important thing to know at this time is that a JumpList contains JumpListLinks. These links consists of a path and arguments that when the JumpListLink is clicked it runs the path with the arguments via a command.

So in the code above, all you need to is change the “crabs”, “prawns” etc to names that are more relevant to your application. Don’t forget to also add the event to the form using the Properties window in VS.

If you run your project now you will notice that your JumpList appears but when you click one of your JumpList items it opens a new instance of your application. How annoying!

 

Getting the JumpList Items to change your application

As we have discovered the JumpList item, when clicked opens up a new instance, in this tutorial we don’t want this to happen. so how do we get round it? Well the tutorial i mentioned before has a rather complex solution which i felt myself slipping into a comma just looking at it.

The key problem is that we somehow need the new instance to talk to the running one and tell it that the user has clicked the JumpList item.

The solution i found easiest was to uses the SendMessage API and i used this page to learn how.

The first thing we need to do is, when the application is first open we need to read the arguments passed to it and look out for the ones we are passing when we set up the JumpList (“crabs”, “prawns”). The  code below can be added to the Program.cs file within the main method. Ive modified the Main method by adding the argStrings.

try
{
     if (args[0] == "crabs")
     {
          //get this running process
          Process proc = Process.GetCurrentProcess();
          //get all other (possible) running instances
          Process[] processes = Process.GetProcessesByName(proc.ProcessName);

          if (processes.Length > 1)
          {
                //iterate through all running target applications      
                foreach (Process p in processes)
                {
                    if (p.Id != proc.Id)
                    {
                          //now send the RF_TESTMESSAGE to the running instance
                          SendMessage(p.MainWindowHandle, RF_TESTMESSAGE, 
                                                   IntPtr.Zero, IntPtr.Zero);
                          Environment.Exit(0);
                    }
                }
           }
      }
}
catch (Exception)
{

}

Now pretty much all of that code is borrowed from the tutorial i mentioned above. What it basically does is find all the running instances of the application and then sends a message to each of them. You should also add the following within the Program class block of your Program.cs file.

     
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hwnd, uint Msg, 
                                            IntPtr wParam, IntPtr lParam);
private const int RF_TESTMESSAGE = 0xA123;

Now when we click the JumpList item we send a message to the application and then close our second instance (confused yet?)

All we have to do next is add some code into our application that will accept the message and then perform an action for us when it gets the message.

so we do that in the following code:

        protected override void WndProc(ref Message message)
        {
            //filter the RF_TESTMESSAGE
            if (message.Msg == RF_TESTMESSAGE)
            {
                MessageBox.Show("crabs");
            }
            //be sure to pass along all messages to the base also
            base.WndProc(ref message);
        }

This code will read in although messages sent to the process and if the message is the one we sent it will show the MessageBox.

With this now in place we are finished!! now when you click your JumpList item it will pop up with a message box saying crabs!

I hope that’s an easier to understand approach to using JumpLists. I would love to hear your comments and feedback.

 

Comments

  • TonyIsBack says:

    Thx for this superb code.

    If you want your application to display multiple MessageBoxes without closing the previous, you have to use Tasks:

    protected override void WndProc(ref Message message)
    {
    //filter the RF_TESTMESSAGE
    if (message.Msg == RF_TESTMESSAGE)
    {
    var task = new Task(() => ShowMessage());
    task.Start();
    }
    //be sure to pass along all messages to the base also
    base.WndProc(ref message);
    }
    private void ShowMessage()
    {
    MessageBox.Show(“crabs”);
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

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=""> <strike> <strong>