Jump to content

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

 

Regards,
 

  • 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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...