Jump to content

Detect right-click on Tray menu item


Recommended Posts

In an AutoIt app with a tray menu created using the TrayCreateItem function, is there a way to detect if an item in the tray menu is right-clicked vs the usual left-click and then act accordingly?

As an example, in the help file example script for TrayGetMessage (modified below), suppose I wanted to show a more detailed MsgBox if the $idAbout item was right-clicked, vs the standard MsgBox if it was left-clicked.

I've added Cases to the Switch conditional to watch for all of the various Tray_Events but I'm finding that right-clicking on a tray item doesn't produce any event. The only time I get a $TRAY_EVENT_SECONDARYDOWN and $TRAY_EVENT_SECONDARYUP event is if I right-clicked on the tray icon to display the tray, and then left-clicked on a tray item. And in that case I get those two right-click events just before the tray item's event.

But what I need is a way to detect when the tray item is right-clicked. I don't care whether it was a left-click or a right-click on the tray icon that initially displayed the tray menu. I only care which mouse button was used to click on the tray item itself.

#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.

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
        Local $TrayMsg = TrayGetMsg()
        Switch $TrayMsg
            Case $idAbout ; Display a message box about the AutoIt version and installation path of the AutoIt executable.
                ConsoleWrite("$idAbout" & @CRLF)
                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.
                ConsoleWrite("$idExit" & @CRLF)
                ExitLoop
            Case 0
                ; $TRAY_EVENT_NONE
            Case -3
                ConsoleWrite("$TRAY_EVENT_SHOWICON = -3" & @CRLF)
            Case -4
                ConsoleWrite("$TRAY_EVENT_HIDEICON = -4" & @CRLF)
            Case -5
                ConsoleWrite("$TRAY_EVENT_FLASHICON = -5" & @CRLF)
            Case -6
                ConsoleWrite("$TRAY_EVENT_NOFLASHICON = -6" & @CRLF)
            Case -7
                ConsoleWrite("$TRAY_EVENT_PRIMARYDOWN = -7 : the primary mouse button was pressed" & @CRLF)
            Case -8
                ConsoleWrite("$TRAY_EVENT_PRIMARYUP = -8 : the primary mouse button was released" & @CRLF)
            Case -9
                ConsoleWrite("$TRAY_EVENT_SECONDARYDOWN = -9 : the secondary mouse button was pressed" & @CRLF)
            Case -10
                ConsoleWrite("$TRAY_EVENT_SECONDARYUP = -10 : the secondary mouse button was released" & @CRLF)
            Case -11
                ; $TRAY_EVENT_MOUSEOVER
            Case -12
                ConsoleWrite("$TRAY_EVENT_MOUSEOUT = -12" & @CRLF)
            Case -13
                ConsoleWrite("$TRAY_EVENT_PRIMARYDOUBLE = -13 : the primary mouse button was double pressed" & @CRLF)
            Case -14
                ConsoleWrite("$TRAY_EVENT_SECONDARYDOUBLE = -14 : the secondary mouse button was double pressed" & @CRLF)
            Case Else
                ConsoleWrite($TrayMsg & @CRLF)
        EndSwitch
    WEnd
EndFunc   ;==>Example

 

Link to post
Share on other sites

AFAIK -- Not possible with the actual Tray* functions.  But it is (of course) possible if you create your own tray menu.  Read MSDN to learn how to create a notification icon (ref _WinAPI_ShellNotifyIcon).

As described in MSDN documentation, you will need to create a popup menu (ref : _GUICtrlMenu_CreatePopup), and when you click on the notification icon you can show the popup menu at the location of your choice (ref : _GUICtrlMenu_TrackPopupMenu).  By registering the $WM_MENURBUTTONUP, you enable a right click on any menu item.

Not obvious, I agree, but doable for sure.

Edited by Nine
Link to post
Share on other sites
49 minutes ago, Nine said:

AFAIK -- Not possible with the actual Tray* functions.  But it is (of course) possible if you create your own tray menu.

Hand-rolling a system tray had crossed my mind, but I've had my fill of doing that with VB6 applications I've created. That's one thing I've really appreciated about AutoIt - how easy it is to have a tray menu without having to manually muck around in its guts.

Kinda seems like if we had a TrayRegisterMessage function similar to the GUIRegisterMessage function, it would make this possible. But oh well. I'll just rethink my UI.

Thanks!

Edited by TimRude
Link to post
Share on other sites

This is aimed at whoever is interested in the subject.  Here an example how to have a right-clickable item with a notification icon.

#NoTrayIcon

#include <GUIConstants.au3>
#include <GuiMenu.au3>
#include <WinAPIShellEx.au3>
#include <SendMessage.au3>

Opt("MustDeclareVars", True)

Global Const $WM_NOTIFYTRAY = $WM_USER + 1
Global Const $HWND_MESSAGE = -3 ;create a message-only window when set as Parent
Global $idShowMenu, $idRightSave, $hGUI

Example()

Func Example()
  $hGUI = GUICreate("", Default, Default, Default, Default, Default, Default, $HWND_MESSAGE)
  $idShowMenu = GUICtrlCreateDummy()
  $idRightSave = GUICtrlCreateDummy()
  Local $idOpen = GUICtrlCreateDummy()
  Local $idSave = GUICtrlCreateDummy()
  Local $idExit = GUICtrlCreateDummy()
  GUISetState(@SW_SHOWNA)

  Local $hMenu = _GUICtrlMenu_CreatePopup()
  _GUICtrlMenu_InsertMenuItem($hMenu, 0, "Open", $idOpen)
  _GUICtrlMenu_InsertMenuItem($hMenu, 1, "Save", $idSave)
  _GUICtrlMenu_InsertMenuItem($hMenu, 3, "", 0)
  _GUICtrlMenu_InsertMenuItem($hMenu, 3, "Exit", $idExit)

  Local $tNOTIFYICONDATA = DllStructCreate($tagNOTIFYICONDATA)
  $tNOTIFYICONDATA.Size = DllStructGetSize($tNOTIFYICONDATA)
  $tNOTIFYICONDATA.hWnd = $hGUI
  $tNOTIFYICONDATA.Flags = BitOR($NIF_MESSAGE, $NIF_ICON, $NIF_TIP)
  $tNOTIFYICONDATA.tip = "Test"
  $tNOTIFYICONDATA.ID = 2
  $tNOTIFYICONDATA.CallbackMessage = $WM_NOTIFYTRAY
  $tNOTIFYICONDATA.hIcon = _WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 155, 16, 16)
  _WinAPI_ShellNotifyIcon($NIM_ADD, $tNOTIFYICONDATA)

  GUIRegisterMsg($WM_NOTIFYTRAY, WM_NOTIFYTRAY)
  GUIRegisterMsg($WM_MENURBUTTONUP, WM_MENURBUTTONUP)

  While True
    Switch GUIGetMsg()
      Case $idOpen
        ConsoleWrite("Open" & @CRLF)
      Case $idSave
        ConsoleWrite("Save" & @CRLF)
      Case $idExit
        ExitLoop
      Case $idShowMenu
        _GUICtrlMenu_TrackPopupMenu($hMenu, $hGUI, -1, -1, 0, 0)
      Case $idRightSave
        ConsoleWrite("Right click on Save" & @CRLF)
    EndSwitch
  WEnd

  _GUICtrlMenu_DestroyMenu($hMenu)
  _WinAPI_ShellNotifyIcon($NIM_DELETE, $tNOTIFYICONDATA)

EndFunc   ;==>Example

Func WM_MENURBUTTONUP($hWnd, $iMsg, $wParam, $lParam)
  If $wParam = 1 Then ; save option
    _SendMessage($hGUI, $WM_CANCELMODE)
    GUICtrlSendToDummy($idRightSave)
  EndIf
EndFunc   ;==>WM_MENURBUTTONUP

Func WM_NOTIFYTRAY($hWnd, $iMsg, $wParam, $lParam)
  Local $iCode = _WinAPI_LoWord($lParam)
  If $iCode = $WM_LBUTTONDOWN Then GUICtrlSendToDummy($idShowMenu)
EndFunc   ;==>WM_NOTIFYTRAY

 

Edited by Nine
Link to post
Share on other sites

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...