autohotkeywindows-10system-tray

Right Click on Tray Icon in Windows 10 with AutoHotKey


In Windows 7, I had an AutoHotKey script that would automatically Right-Click on a tray icon.

#Include %A_Scriptdir%\TrayIcon.ahk
TrayIcon_Button("CCC.exe", "R")

Which used the TrayIcon.ahk library from FanaticGuru's post.

This worked just fine on Windows 7, but no longer works on Windows 10.

Is there a way to right click on a TrayIcon in an AutoHotKey script on Windows 10?

Here is the TrayIcon_Button function from the library. I refrained from posting the entire library since it is fairly long.

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: TrayIcon_Button
; Description ..: Simulate mouse button click on a tray icon.
; Parameters ...: sExeName - Executable Process Name of tray icon.
; ..............: sButton  - Mouse button to simulate (L, M, R).
; ..............: bDouble  - True to double click, false to single click.
; ..............: index    - Index of tray icon to click if more than one match.
; ----------------------------------------------------------------------------------------------------------------------
TrayIcon_Button(sExeName, sButton := "L", bDouble := false, index := 1)
{
    Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
    DetectHiddenWindows, On
    WM_MOUSEMOVE      = 0x0200
    WM_LBUTTONDOWN    = 0x0201
    WM_LBUTTONUP      = 0x0202
    WM_LBUTTONDBLCLK = 0x0203
    WM_RBUTTONDOWN    = 0x0204
    WM_RBUTTONUP      = 0x0205
    WM_RBUTTONDBLCLK = 0x0206
    WM_MBUTTONDOWN    = 0x0207
    WM_MBUTTONUP      = 0x0208
    WM_MBUTTONDBLCLK = 0x0209
    sButton := "WM_" sButton "BUTTON"
    oIcons := {}
    oIcons := TrayIcon_GetInfo(sExeName)
    msgID  := oIcons[index].msgID
    uID    := oIcons[index].uID
    hWnd   := oIcons[index].hWnd
    if bDouble
        PostMessage, msgID, uID, %sButton%DBLCLK, , ahk_id %hWnd%
    else
    {
        PostMessage, msgID, uID, %sButton%DOWN, , ahk_id %hWnd%
        PostMessage, msgID, uID, %sButton%UP, , ahk_id %hWnd%
    }
    DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
    return
}

Solution

  • I tested it on Windows 10. It was not working for the icons hidden under overflow window, although it was working perfectly for the visible icons.

    Update these three lines in TrayIcon_GetInfo() for a quick solution

    For key, sTray in ["Shell_TrayWnd","NotifyIconOverflowWindow"]
    SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class %sTray%   ; TB_BUTTONCOUNT
    SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32%idxTB%, ahk_class %sTray%   ; TB_GETBUTTON
    

    Replace them with

    For key, sTray in ["NotifyIconOverflowWindow", "Shell_TrayWnd"]
    SendMessage, 0x418, 0, 0, ToolbarWindow32%key%, ahk_class %sTray%   ; TB_BUTTONCOUNT
    SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32%key%, ahk_class %sTray%   ; TB_GETBUTTON
    

    Update: To awesome users who have upgraded to Windows 1607, it is broken again :)

    To make it work again in Windows 10 1607, first follow those last rules. After that replace these with:

    SendMessage, 0x418, 0, 0, ToolbarWindow32%key%, ahk_class %sTray%   ; TB_BUTTONCOUNT
    SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32%key%, ahk_class %sTray%   ; TB_GETBUTTON
    

    with

    if ("Shell_TrayWnd" == sTray) {
        SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class %sTray%   ; TB_BUTTONCOUNT
    } else if ("NotifyIconOverflowWindow" == sTray) {
        SendMessage, 0x418, 0, 0, ToolbarWindow32%key%, ahk_class %sTray%   ; TB_BUTTONCOUNT
    }
    if ("Shell_TrayWnd" == sTray) {
        SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32%idxTB%, ahk_class %sTray%   ; TB_GETBUTTON
    } else if ("NotifyIconOverflowWindow" == sTray) {
        SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32%key%, ahk_class %sTray%   ; TB_GETBUTTON
    }
    

    Note: I don't think any of these changes are backward compatible.