July 13, 2006

Activating System Tray Icons

Filed under: Automation,Scripting — Marcus Tettmar @ 8:47 am

This one has bugged me for years – how to automate activating a system tray icon. For starters, the System Tray is designed to be manipulated with the mouse. We could send mouse clicks to icons in the system tray but for the fact that icons don’t always appear in the same place in the tray. Some systems contract and expand the system tray and on startup icons can be reshuffled and appear in a different order. So sending mouse events is no good.

Well it turns out there is a way to control the system tray with the keyboard. I hadn’t realised this. Thanks to Henk for discovering this. Henk demonstrates here that if you press the Windows key to open the start menu, then Escape to close the start menu keyboard focus is now on the Start button. If you then press Tab a few times focus ends up in the System Tray. If you hover over a System Tray icon you will see a Tool Tip appear above it showing the name of the application. Well the first letter of this text will select this icon. So once you’ve tabbed into the System Tray you can now press the letter key corresponding to the first letter of the icon’s title and it will be selected. Then pressing Enter will activate it.

The number of tabs you need to send to get to the System Tray depends on how you have your task bar set up. If you have the QuickLaunch toolbar enabled you’d need an extra Tab. And in XP with the contracting/expanding System Tray you need to press the right arrow key to move off the contract/expand button. So this approach is not entirely portable but will work on your system.

So I gave this some more thought and came up with a portable approach which focuses the System Tray area directly – without having to open the Start menu and tab around. My approach uses the Win32 API functions FindWindow and FindWindowEx to find the handle of the System Tray Notification Area and then focus it directly. Here’s the code:

Let>WIN_USEHANDLE=1
LibFunc>User32,FindWindowA,h1,Shell_TrayWnd,
LibFunc>User32,FindWindowExA,h2,h1,0,TrayNotifyWnd,
LibFunc>User32,FindWindowExA,h3,h2,0,SysPager,
LibFunc>User32,FindWindowExA,h4,h3,0,ToolbarWindow32,Notification Area
SetFocus>h4
//Change to first letter of icon to activate
Send>v
//If more than one with same first letter, then repeat above line for each
Press Enter

Thanks again to Henk for the tip. See the forum post here.