Something like this here:
#include <Array.au3>
#include <Constants.au3>
#include <WindowsConstants.au3>
#include <SendMessage.au3>
#include <WinAPISysWin.au3>
#include <WinAPIGdi.au3>
#include <WinAPIShellEx.au3>
Global Const $WM_NOTIFYICON = $WM_USER + 1
Global Const $sWinTitle = "TrayExample"
AutoItWinSetTitle($sWinTitle)
Opt("TrayMenuMode", 3)
Global $hHWND = WinGetHandle($sWinTitle)
Global $hTaskbar = WinGetHandle("[CLASS:Shell_TrayWnd]")
Global $hTray
Example()
Func Example()
Local $idAbout = TrayCreateItem("About")
TrayCreateItem("")
Local $idExit = TrayCreateItem("Exit")
HotKeySet("{F9}", ShowTrayMenu)
$a = _WinAPI_EnumChildWindows($hTaskbar)
$iPos = _ArraySearch($a, "TrayNotifyWnd", 0, 0, 0, 0, 1, 1)
If Not @error Then
$hTray = $a[$iPos][0]
EndIf
While True
Switch TrayGetMsg()
Case $idExit
ExitLoop
Case $idAbout
MsgBox($MB_SYSTEMMODAL, "About", "AutoIt tray menu example." & @CRLF & @CRLF & _
"Version: " & @AutoItVersion & @CRLF & _
"Install Path: " & StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", 0, -1) - 1))
EndSwitch
If CheckMouseOverTrayIcon() = 1 And WinExists("[CLASS:#32768]") = 0 Then ShowTrayMenu()
WEnd
EndFunc ;==>Example
Func ShowTrayMenu()
_SendMessage($hHWND, $WM_NOTIFYICON, 0, $WM_LBUTTONDOWN)
EndFunc ;==>ShowTrayMenu
Func CheckMouseOverTrayIcon()
Local $tNID = DllStructCreate("dword cbSize;hwnd hWnd;uint uID;uint uFlags")
Local $hTrayWnd = _WinAPI_GetShellWindow()
If $hTrayWnd = 0 Then Return -1
DllStructSetData($tNID, "cbSize", DllStructGetSize($tNID))
DllStructSetData($tNID, "hWnd", $hTray)
DllStructSetData($tNID, "uID", 1)
Local $tRECT = _WinAPI_ShellNotifyIconGetRect(WinGetHandle(AutoItWinGetTitle()), 1)
If @error Then Return -2
Local $aPos = _WinAPI_GetPosFromRect($tRECT)
Local $aMousePos = MouseGetPos()
If $aMousePos[0] >= $aPos[0] And $aMousePos[0] <= $aPos[0] + $aPos[2] And $aMousePos[1] >= $aPos[1] And $aMousePos[1] <= $aPos[1] + $aPos[3] Then
Return 1
EndIf
Return 0
EndFunc ;==>CheckMouseOverTrayIcon
Will work properly when icon is visible on the taskbar. Tested on Win11 24H2.