Jump to content

[SOLVED] _GUICtrlMenu_CreatePopup() on Tray icon


Recommended Posts

The code, then the story.

#NoTrayIcon
#include <Debug.au3>
#include <File.au3>
#include <Array.au3>

#include <GUIConstantsEx.au3>
#include <GuiMenu.au3>
#include <WinAPIError.au3>
#include <WindowsConstants.au3>


#include <MsgBoxConstants.au3>
#include <StringConstants.au3>
#include <TrayConstants.au3>

Global $hDLLuser32 = DllOpen("user32.dll")

; you'll need this !!
HotKeySet("{ESC}", "Terminate")
Func Terminate()
    Exit 0
EndFunc   ;==>Terminate


Opt("GUIOnEventMode", 1)
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.
Opt("TrayOnEventMode", 1) ; Enable TrayOnEventMode.

Global Enum $e_idOpen = 1000, $e_idSave, $e_idInfo


MyExample()

Func MyExample()
;~  TrayCreateItem("About")
;~  TrayItemSetOnEvent(-1, "About")

;~  TrayCreateItem("") ; Create a separator line.

;~  TrayCreateItem("Exit")
;~  TrayItemSetOnEvent(-1, "ExitScript")

    TraySetOnEvent($TRAY_EVENT_SECONDARYDOWN, "WM_CONTEXTMENU") ; Display the About MsgBox when the tray icon is double clicked on with the primary mouse button.

    TraySetState($TRAY_ICONSTATE_SHOW) ; Show the tray menu.

    ; Register message handlers
    GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
    GUIRegisterMsg($WM_CONTEXTMENU, "WM_CONTEXTMENU")

    While 1
        Sleep(100) ; An idle loop.
    WEnd
EndFunc   ;==>Example

Func About()
    ; 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.
EndFunc   ;==>About

Func ExitScript()
    Exit
EndFunc   ;==>ExitScript




Func OriginalExample()
    ; Create GUI
    GUICreate("Menu", 400, 300)
    GUISetState(@SW_SHOW)

    ; Register message handlers
    GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
    GUIRegisterMsg($WM_CONTEXTMENU, "WM_CONTEXTMENU")

    ; Loop until the user exits.
    Do
    Until Not Sleep(50) ; GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc   ;==>Example

; Handle WM_COMMAND messages
Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    ConsoleWrite('+ Func WM_COMMAND(' & $hWnd & ', ' & $iMsg & ', ' &  $wParam & ', ' &  $lParam & ')' & @CRLF)
    #forceref $hWnd, $iMsg, $lParam
    Switch $wParam
        Case $e_idOpen
            _WinAPI_ShowMsg("Open")
        Case $e_idSave
            _WinAPI_ShowMsg("Save")
        Case $e_idInfo
            _WinAPI_ShowMsg("Info")
    EndSwitch
EndFunc   ;==>WM_COMMAND

; Handle WM_CONTEXTMENU messages
Func WM_CONTEXTMENU($hWnd = 0, $iMsg = 0, $wParam = 0, $lParam = 0)
    #forceref $hWnd, $iMsg, $lParam
    ConsoleWrite('+ Func WM_CONTEXTMENU(' & Eval('hWnd') & ', ' & Eval('iMsg') & ', ' & Eval('wParam') & ', ' & Eval('lParam') & ')' & @CRLF)
    Local $hMenu

    $hMenu = _GUICtrlMenu_CreatePopup()
    _GUICtrlMenu_InsertMenuItem($hMenu, 0, "Open", $e_idOpen)
    _GUICtrlMenu_InsertMenuItem($hMenu, 1, "Save", $e_idSave)
    _GUICtrlMenu_InsertMenuItem($hMenu, 3, "", 0)
    _GUICtrlMenu_InsertMenuItem($hMenu, 3, "Info", $e_idInfo)
;~  _GUICtrlMenu_TrackPopupMenu($hMenu, WinGetHandle(AutoItWinGetTitle()))
    TrackPopupMenu(WinGetHandle(AutoItWinGetTitle()), $hMenu, MouseGetPos(0), MouseGetPos(1))
    _GUICtrlMenu_DestroyMenu($hMenu)
    Return True
EndFunc   ;==>WM_CONTEXTMENU

; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func ShowMenu($hWnd, $idCtrl, $idContext)
    Local $aPos, $x, $y
    Local $hMenu = GUICtrlGetHandle($idContext)
    $aPos = ControlGetPos($hWnd, "", $idCtrl)
    $x = $aPos[0]
    $y = $aPos[1] + $aPos[3]
    ClientToScreen($hWnd, $x, $y)
    TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc   ;==>ShowMenu

; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
    Local $tPoint = DllStructCreate("int;int")
    DllStructSetData($tPoint, 1, $x)
    DllStructSetData($tPoint, 2, $y)
    DllCall($hDLLuser32, "int", "ClientToScreen", "hwnd", $hWnd, "struct*", $tPoint)
    $x = DllStructGetData($tPoint, 1)
    $y = DllStructGetData($tPoint, 2)
    ; release Struct not really needed as it is a local
    $tPoint = 0
EndFunc   ;==>ClientToScreen

; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd)
Func TrackPopupMenu($hWnd, $hMenu, $x, $y)
    ConsoleWrite('!+ Func TrackPopupMenu' & @CRLF)
    DllCall($hDLLuser32, "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
    ConsoleWrite('!- Func TrackPopupMenu' & @CRLF)
EndFunc   ;==>TrackPopupMenu

I would like to have a TraySetOnEvent() ( or the like ) and to build the TrayCreateItem() on the fly.
I figure that _GUICtrlMenu_CreatePopup() then _GUICtrlMenu_DestroyMenu($hMenu) would be the way to go BUT it does not work the way I coded it. ( as I can not come up with the idea )

Help.

How would I have a tray menu that is build/re-build each time the tray icon is $TRAY_EVENT_SECONDARYUP ?.

Thanks.

PS: Since the code does not work, there is a {ESC} Hotkey to exit.
 

Edited by argumentum
solved

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Why so complicated code?

#NoTrayIcon

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <TrayConstants.au3>
#include <GuiMenu.au3>

Opt("GUIOnEventMode", 1)
Opt("TrayMenuMode", 3)
Opt("TrayOnEventMode", 1)

Global $hGui

MyExample()

Func MyExample()
  $hGui = GUICreate("")
  TraySetOnEvent($TRAY_EVENT_SECONDARYDOWN, "MyTrayMenu")
  TraySetState($TRAY_ICONSTATE_SHOW) ; Show the tray menu.

  While 1
    Sleep(10) ; An idle loop.
  WEnd
EndFunc

Func MyTrayMenu()
  Local Enum $e_idOpen = 1000, $e_idSave, $e_idInfo, $e_idClose
  Local $hMenu = _GUICtrlMenu_CreatePopup()
  _GUICtrlMenu_AddMenuItem($hMenu, "Open", $e_idOpen)
  _GUICtrlMenu_AddMenuItem($hMenu, "Save", $e_idSave)
  _GUICtrlMenu_AddMenuItem($hMenu, "", 0)
  _GUICtrlMenu_AddMenuItem($hMenu, "Info", $e_idInfo)
  _GUICtrlMenu_AddMenuItem($hMenu, "", 0)
  _GUICtrlMenu_AddMenuItem($hMenu, "Close", $e_idClose)
  Switch _GUICtrlMenu_TrackPopupMenu( $hMenu, $hGui, -1, -1, 1, 1, 2 )
    Case $e_idOpen
      ConsoleWrite( "Open" & @CRLF )
    Case $e_idSave
      ConsoleWrite( "Save" & @CRLF )
    Case $e_idInfo
      ConsoleWrite( "Info" & @CRLF )
    Case $e_idClose
      ConsoleWrite( "Close" & @CRLF )
      Exit
  EndSwitch
  _GUICtrlMenu_DestroyMenu($hMenu)
EndFunc

 

Link to comment
Share on other sites

6 hours ago, LarsJ said:

Why so complicated code?

Because I was "grrr" :mad2:.

The greater issue is that it does not behave well. On any context-menu, if you disregard it, it goes away. This methodology does not do that. If the menu is not clicked, it lingers. Stays open.

I think I'll make a small temp GUI behind the context menu to have it well behaved ( unless, of course, better behaved code "pops up" ( by you maybe :) )).

I'll write my concept in a moment ( or half an hour ).

PS: Read the code that you posted. The first time, I copy'n'paste, run, ...all without reading the code =/

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Thanks a million @LarsJ. All that was missing was the GUISetState(@SW_SHOW) at the time of showing the context menu    =D 

#NoTrayIcon

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <TrayConstants.au3>
#include <GuiMenu.au3>

Opt("GUIOnEventMode", 1)
Opt("TrayMenuMode", 3)
Opt("TrayOnEventMode", 1)

Global $hGui

MyExample()

Func MyExample()
    AutoItWinSetTitle(@ScriptFullPath & @AutoItPID)
    $hGui = GUICreate("MyExample", 0, 0, -1, -1, BitOR($WS_SYSMENU, $WS_POPUP), $WS_EX_TOPMOST, WinGetHandle(@ScriptFullPath & @AutoItPID))
    GUISetState(@SW_HIDE)
    TraySetOnEvent($TRAY_EVENT_SECONDARYUP, "MyTrayMenu")
    TraySetState($TRAY_ICONSTATE_SHOW) ; Show the tray menu.
    While Sleep(10) ; An idle loop.
    WEnd
EndFunc   ;==>MyExample

Func MyTrayMenu()
    Local Enum $e_idOpen = 1000, $e_idSave, $e_idInfo, $e_idClose
    Local $hMenu = _GUICtrlMenu_CreatePopup()
    _GUICtrlMenu_AddMenuItem($hMenu, "Open", $e_idOpen)
    _GUICtrlMenu_AddMenuItem($hMenu, "Save", $e_idSave)
    _GUICtrlMenu_AddMenuItem($hMenu, "", 0)
    _GUICtrlMenu_AddMenuItem($hMenu, "Info", $e_idInfo)
    _GUICtrlMenu_AddMenuItem($hMenu, "", 0)
    _GUICtrlMenu_AddMenuItem($hMenu, "Close", $e_idClose)
    GUISetState(@SW_SHOW) ; < ----- this solves the problem   =)
    Switch _GUICtrlMenu_TrackPopupMenu($hMenu, $hGui, -1, -1, 1, 1, 2)
        Case $e_idOpen
            ConsoleWrite("Open" & @CRLF)
        Case $e_idSave
            ConsoleWrite("Save" & @CRLF)
        Case $e_idInfo
            ConsoleWrite("Info" & @CRLF)
        Case $e_idClose
            ConsoleWrite("Close" & @CRLF)
            Exit
    EndSwitch
    _GUICtrlMenu_DestroyMenu($hMenu)
    GUISetState(@SW_HIDE)
EndFunc   ;==>MyTrayMenu

 

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
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
 Share

  • Recently Browsing   0 members

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