Search code examples
winapinotification-area

Programmatically obtaining a Windows application's tray menu items


I have an application with a tray menu and I'm trying to automate some tests that involve the tray menu. Basically I need obtain the tray menu's items and do stuff with them. However, I've only been able to find ways to programmatically obtain menu items for within the application. But my automation tests are going to be an external application, so that doesn't help me.

How can I obtain an external application's tray menu items programmatically?


Solution

  • There are ways to enumerate/access the tray icons themselves (usually involving hooking into the notification tray itself, or using UI Automation), but there is no way to access a popup menu that appears when a tray icon is clicked on. The reason is because the icon's owning application receives a message when the click occurs and then acts accordingly, which usually involves displaying its own popup menu. There is no menu associated with the icon itself.

    For what you are attempting, you would have to enumerate the icons and figure out which icon belongs to the app you are interested in (not a trivial task on its own), then simulate a click on the icon so the app displays its popup menu. See the following question for some details:

    Finding and simulating a click on a system tray icon?

    Interacting with the popup menu once it is displayed will be more difficult. You won't have access to the menu itself. You will likely have to resort to just issuing mouse events via mouse_event() or SendInput() to move the mouse cursor over the menu and click its items (assuming they appear in predictable locations relative to the icon).

    If you can obtain the icon's HWND+ID or GUID (by hooking the notification tray itself), you can use Shell_NotifyIconGetRect() to get the icon's coordinates, at least.