I frequently run into lost souls using our competitors' tools asking how they can control what happens when they click an icon in the system tray. The answer they get is almost universally "you can't control that, Windows handles that for you" but that just isn't even close to true.

So, if Windows doesn't control what happens, how are clicks on the icons supposed to work? There are User Experience Guidelines you can follow, but there are no rules. Ultimately the decision is up to the application that receives the mouse clicks.

I'm going to show you just how much control you have over the behavior of your tray icons using SWF Studio. If you're using one of those other tools, don't worry, your users probably won't notice that weird tray icon behavior...

Default Behavior in SWF Studio

You can add a tray icon to your application with a single line of code ssCore.Tray.addIcon({}); or by enabling the "Display an icon in the system tray" checkbox on the Application Tab.

Without setting up any events to handle mouse clicks you get some default behavior for free. When you singe left click on the tray icon your application gets focus and if it was minimized it will be restored before it gets focus. A single right click or a double click will do nothing, except steal the input focus from your application, the same as clicking anywhere outside your application would.

This may not be the behavior you want for your application so let's find out what we can do about changing it.

Taking Control of the Tray

The first thing we'll do is set up an onTrayClick event handler that will be called when the user clicks on our tray icon. We won't do anything in the event handler which means that SWF Studio will just eat the mouse clicks. This isn't very interesting but it does prove that we have complete control over the behavior of the tray icon.

ssCore.init();
ssDefaults.synchronousCommands = true;

ssCore.Tray.addIcon({});

ssCore.Tray.setNotify({event:"onTrayClick"}, {callback:onTrayClick});

function onTrayClick(ret_obj, cb_obj, err_obj)
{
   // do nothing
}

Responding to Single Clicks

Now let's try something a bit more useful. On a single left click we'll restore the application (if it's minimized) and make sure it gets focus. On a single middle click we'll minimize the application, and on a single right click we'll display a context menu without restoring the application or giving it focus.

ssCore.init();
ssDefaults.synchronousCommands = true;

ssCore.Tray.addIcon({});

ssCore.Tray.setNotify({event:"onTrayClick"}, {callback:onTrayClick});

ssCore.Popup.newMenu({name:"MyTrayMenu"});
ssCore.Popup.addItem({name:"MyTrayMenu", parent:"0", type:"item", id:"1", text:"Item 1"});
ssCore.Popup.addItem({name:"MyTrayMenu", parent:"0", type:"item", id:"2", text:"Item 2"});
ssCore.Popup.addItem({name:"MyTrayMenu", parent:"0", type:"item", id:"3", text:"Item 3"});

function onTrayClick(ret_obj, cb_obj, err_obj)
{
   if (ret_obj.result == "LEFTBUTTON")
   {
      ssCore.Win.setFocus({});
   }

   if (ret_obj.result == "MIDDLEBUTTON")
   {
      ssCore.win.minimize({});
   }

   if (ret_obj.result == "RIGHTBUTTON")
   {
      ssCore.Popup.show({name:"MyTrayMenu"});
   }
}

Adding Double Click Support

Setting up an event handler for double clicks is just as easy as for single clicks but there's a problem lurking just under the covers. If you just set up the new double click event handler, SWF Studio will call the single click handler when the first click arrives and the double click handler if the second click arrives (within the double click time limit set up in Windows).

How do we determine when we should handle a single click versus a double click?

There's a simple solution and it's the same one Windows uses. When the first click is detected we won't execute it immediately. Instead we'll wait a half-second and see if the other half of a double click is received. If not, we'll call the left click handler. If a second click is received we'll scrap the queued function call and perform the double click action instead.

ssCore.init();
ssDefaults.synchronousCommands = true;

ssCore.Tray.addIcon({});

ssCore.Tray.setNotify({event:"onTrayClick"}, {callback:onTrayClick});
ssCore.Tray.setNotify({event:"onTrayDoubleClick"}, {callback:onTrayDoubleClick});

var g_idLeftClickDelay;

function onLeftClick()
{
   // don't do this again until the next click
   clearInterval(g_idLeftClickDelay);

   ssCore.win.setFocus({});
}

function onTrayClick(ret_obj, cb_obj, err_obj)
{
   if (ret_obj.result == "LEFTBUTTON")
   {
      // queue up the function we want to execute on
      // a single left click for 1/2 second from now
      g_idLeftClickDelay = setInterval(onLeftClick, 500);
   }
}

function onTrayDoubleClick(ret_obj, cb_obj, err_obj)
{
   if (ret_obj.result == "LEFTBUTTON")
    {
      // ignore the single left click that we queued up,
      clearInterval(g_idLeftClickDelay);

      ssCore.Win.restore({});
      ssCore.App.showMsgBox({prompt:"that was a double click"});
   }

   // NOTE: we could also handle double clicks for the
   // MIDDLE and RIGHT mouse buttons they same way
}

With that we've taken complete control of what happens in response to single and double click events on our tray icon. You can substitute whatever code you want in place of the example handlers shown here to make your application do anything you want.

And there's still more you can do with the Tray commands in SWF Studio...

· changing the tray icon on the fly
· showing balloon help
· showing tooltips when the user hovers over the tray icon
· detecting when the user is hovering over the tray icon

SWF Studio is well known for it's deep functionality and our tray icon support is no exception. Other tools say they have tray icon support but you won't find functionality like this in any other swf2exe application. Our attention to detail is what makes the difference between a good application and a great application.

Download your FREE trial version of SWF Studio today.

tracyclick.zip 7 KB