Jump to content

How to show tray menu without clicking tray icon?


Go to solution Solved by Nine,

Recommended Posts

Posted

How to show tray menu without clicking on tray icon? Or Click on tray icon automatically!

#NoTrayIcon
#include <MsgBoxConstants.au3>
#include <StringConstants.au3>
#include <TrayConstants.au3> ; Required for the $TRAY_ICONSTATE_SHOW constant.

Opt("TrayMenuMode", 3) ; The default tray menu items will not be shown and items are not checked when selected. These are options 1 and 2 for TrayMenuMode.
HotKeySet("{F12}", "_ShowTrayMenu") ; Đặt Hotkey là phím F12
Example()

Func Example()
    Local $idAbout = TrayCreateItem("About")
    TrayCreateItem("")     ; Create a separator line.
    Local $idExit = TrayCreateItem("Exit")
    TraySetState($TRAY_ICONSTATE_SHOW)     ; Show the tray menu.
    While 1
        Switch TrayGetMsg()
            Case $idAbout             ; Display a message box about the AutoIt version and installation path of the AutoIt executable.
                MsgBox($MB_SYSTEMMODAL, "", "AutoIt tray menu example." & @CRLF & @CRLF & _
                        "Version: " & @AutoItVersion & @CRLF & _
                        "Install Path: " & StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", $STR_NOCASESENSEBASIC, -1) - 1))                         ; Find the folder of a full path.

            Case $idExit             ; Exit the loop.
                ExitLoop
        EndSwitch
    WEnd
EndFunc   ;==>Example

Func _ShowTrayMenu()
    ;???????????????????????????????????????
EndFunc

 

Enjoy my work? Buy me a 🍻 or tip via ❤️ PayPal

  • Solution
Posted

Another way :

#include <Constants.au3>
#include <WindowsConstants.au3>
#include <SendMessage.au3>

Global Const $WM_NOTIFYICON = $WM_USER + 1
Global Const $sWinTitle = "TrayExample"
AutoItWinSetTitle($sWinTitle)

Opt("TrayMenuMode", 3)

Example()

Func Example()
  Local $idAbout = TrayCreateItem("About")
  TrayCreateItem("")
  Local $idExit = TrayCreateItem("Exit")

  HotKeySet("{F9}", ShowTrayMenu)

  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
  WEnd
EndFunc   ;==>Example

Func ShowTrayMenu()
  _SendMessage(WinGetHandle($sWinTitle), $WM_NOTIFYICON, 0, $WM_LBUTTONDOWN)
EndFunc   ;==>ShowTrayMenu

 

Posted (edited)

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.

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted (edited)

Here's my take including auto-hide after 750ms being off the menu 🙂

Maybe someone has a better method to hide the menu again than "WinActivate(_hWnd_under_Mouse(2))"? Couldn't find a message for that task.

#NoTrayIcon

#include <Array.au3>
#include <Constants.au3>
#include <WindowsConstants.au3>
#include <SendMessage.au3>
#include <WinAPISysWin.au3>
#include <WinAPIGdi.au3>
#include <WinAPIShellEx.au3>
#pragma compile(AutoItExecuteAllowed, true)

Global $hWnd_AutoIt
Global $iPID_Parent = @AutoItPID
Global Const $WM_NOTIFYICON = $WM_USER + 1

If StringInStr($CmdLineRaw, "Monitor_Tray_Menu") Then

    If $CmdLine[0] <> 2 Then Exit
    Sleep(250)
    $hWnd_AutoIt = HWnd($CmdLine[2])
    If Not IsHWnd($hWnd_AutoIt) Then Exit
    $iPID_Parent = WinGetProcess($hWnd_AutoIt)

    Local $i_Timer = TimerInit()

    While Sleep(10)

        If CheckMouseOverTrayIcon() <> 1 And CheckMouseOverTrayMenu() <> 1 Then
            If TimerDiff($i_Timer) > 750 Then
                WinActivate(_hWnd_under_Mouse(2))
                ExitLoop
            EndIf
        Else
            $i_Timer = TimerInit()
        EndIf

        If Not IsHWnd($hWnd_AutoIt) Then ExitLoop
    WEnd

    Exit
EndIf

$hWnd_AutoIt = WinGetHandle(AutoItWinGetTitle())

Opt("TrayMenuMode", 3)

Local $idAbout = TrayCreateItem("About")
TrayCreateItem("")
Local $idExit = TrayCreateItem("Exit")

TraySetState()

HotKeySet("{F9}", ShowTrayMenu)


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 CheckMouseOverTrayMenu() = 0 Then
        ShowTrayMenu()
    EndIf

WEnd


Func ShowTrayMenu()
    If @Compiled Then
        Run(@AutoItExe & " Monitor_Tray_Menu " & WinGetHandle(AutoItWinGetTitle()), @ScriptDir, @SW_HIDE)
    Else
        Run(@AutoItExe & ' "' & @ScriptFullPath & '" Monitor_Tray_Menu ' & WinGetHandle(AutoItWinGetTitle()), @ScriptDir, @SW_HIDE)
    EndIf
    _SendMessage(WinGetHandle(AutoItWinGetTitle()), $WM_NOTIFYICON, 0, $WM_LBUTTONDOWN)
EndFunc   ;==>ShowTrayMenu

Func CheckMouseOverTrayMenu()
    Local $hWnd = _hWnd_under_Mouse(2)
    Local $aWinlist = WinList("[CLASS:#32768]")
    For $i = 1 To $aWinlist[0][0]
        If $aWinlist[$i][1] = $hWnd And WinGetProcess($hWnd) = $iPID_Parent Then
            Return 1
        EndIf
    Next
    Return 0
EndFunc   ;==>CheckMouseOverTrayMenu

Func CheckMouseOverTrayIcon()
    Local $hTrayWnd = _WinAPI_GetShellWindow()
    If $hTrayWnd = 0 Then Return -1
    Local $tRECT = _WinAPI_ShellNotifyIconGetRect($hWnd_AutoIt, 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

Func _hWnd_under_Mouse($hWnd_Type = 1)
    ; $hWnd_Type = 1 > Current Control
    ; $hWnd_Type = 2 > Parent Window of Current Control
    Local $tPoint = DllStructCreate("int X;int Y")
    Local $pMouse = MouseGetPos()
    DllStructSetData($tPoint, "X", $pMouse[0])
    DllStructSetData($tPoint, "Y", $pMouse[1])
    Local $hWnd_Current_Control_under_Mouse = _WinAPI_WindowFromPoint($tPoint)
    If $hWnd_Type = 1 Then
        Return $hWnd_Current_Control_under_Mouse
    Else
        Local $hWnd_Parent_Window_of_Current_Control_under_Mouse = _WinAPI_GetAncestor($hWnd_Current_Control_under_Mouse, $GA_ROOTOWNER)
        Return $hWnd_Parent_Window_of_Current_Control_under_Mouse
    EndIf
EndFunc   ;==>_hWnd_under_Mouse

 

Edited by KaFu
Posted (edited)

Great @KaFu.  Here using my PMT-UDF :

#include <WinAPISysWin.au3>
#include <Constants.au3>
#include <WindowsConstants.au3>
#include <SendMessage.au3>
#include <Array.au3>
#include <WinAPIShellEx.au3>
#include <WinAPIGdi.au3>
#include "..\Files\PMT-UDF.au3"

Global Const $WM_NOTIFYICON = $WM_USER + 1
Global Const $sWinTitle = "TrayExample"
AutoItWinSetTitle($sWinTitle)

Opt("TrayMenuMode", 3)

_PMT_Init()

Example()

Func Example()
  Local $idAbout = TrayCreateItem("About")
  TrayCreateItem("")
  Local $idExit = TrayCreateItem("Exit")

  HotKeySet("{F9}", ShowTrayMenu)

  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() Then ShowTrayMenu()
  WEnd
EndFunc   ;==>Example

Func ShowTrayMenu()
  _PMT_Start("CheckInsideMenu")
  _SendMessage(WinGetHandle($sWinTitle), $WM_NOTIFYICON, 0, $WM_LBUTTONDOWN)
EndFunc   ;==>ShowTrayMenu

Func CheckMouseOverTrayIcon()
  Local $tPoint = _WinAPI_GetMousePos(), $tRECT = _WinAPI_ShellNotifyIconGetRect(WinGetHandle($sWinTitle), 1)
  If @error Then Return False
  Return _WinAPI_PtInRect($tRECT, $tPoint)
EndFunc   ;==>CheckMouseOverTrayIcon

Func CheckInsideMenu()
  Local $bHover = False, $hWnd = WinWait("[CLASS:#32768]"), $tPoint, $hTimer
  While WinExists($hWnd) And Sleep(10)
    $tPoint = _WinAPI_GetMousePos()
    If $hWnd = _WinAPI_WindowFromPoint($tPoint) Then
      $bHover = True
      $hTimer = TimerInit()
    ElseIf $bHover And TimerDiff($hTimer) > 750 Then
      WinClose($hWnd)
    EndIf
  WEnd
EndFunc   ;==>CheckInsideMenu

 

Edited by Nine

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...