How to add JumpLists to a C# Application
Yesterday I thought that I would have a go at adding “JumpLists” to a C# WPF application. I thought it should be simple, perhaps all I would need to do is drag a component into the Visual Studio Designer and then it would be done. Well I was wrong…
JumpLists were introduced in Windows 7 and is a menu that appears when you right click the application icon in the taskbar.
The way I use the JumpList in this tutorial is a simplified approach to the Single Instance taskbar tutorial. 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. So the first step we need to take is to download the Windows API code pack.
Once you have downloaded the API you 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
The first issue you will be faced with is where to put the code, the code wont work in the forms constructor so to overcome 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(); }
I don’t check that the user is running Windows 7 which will cause an Exception with non Windows 7 users so its worth adding a check before running this code.
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 Visual Studio.
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.
Getting the JumpList Items to change your application
So how do we get round the issue of a new instance being opened when the JumpList item is clicked? The tutorial I mentioned before has a rather complex solution. The key problem is that we 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 use the SendMessage API.
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. I’ve modified the Main method by adding the argStrings.
try { if (args[0] == "crabs") { //get this running process var 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) { }
much of that code is borrowed from the tutorial mentioned above. What it 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. 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("hello"); } //be sure to pass along all messages to the base also base.WndProc(ref message); }
This code will read in all the 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 instead of creating a new instance.
I hope that’s an easier to understand approach to using JumpLists. I would love to hear your comments and feedback.
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”);
}
I know this may seem pedantic, but please capitalize “I” when referring to yourself. The article comes across as unprofessional.
Thanks for your feedback Jared. Completely agree with you, it was embarrassing for me to re-read. I have gone through it and hopefully improved it.
Excellent, thanks for the response. Very helpful article, by the way. :)
hi, i use this code in my app but it does not show msg when three options (crabes…) are clicked. It only open new instance when press on my app name in task bar
Note: I am using vs 2013 and windows 10
ok, now jumplist is working but when exe is pinned in taskbar, and does not work when exe is unpinned
Sounds like you have made good progress. I have not tested this on Windows 10 so it would be good to see if you resolve this.
this is also fixed when I placed exe and dll file in my app installed folder. Thanks.
Jumplist fully working when I placed my exe in the folder where my app is installed