argumentum Posted November 26, 2018 Share Posted November 26, 2018 (edited) The code, then the story. expandcollapse popup#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 November 27, 2018 by argumentum solved Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
LarsJ Posted November 26, 2018 Share Posted November 26, 2018 Why so complicated code? expandcollapse popup#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 argumentum 1 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
argumentum Posted November 27, 2018 Author Share Posted November 27, 2018 (edited) 6 hours ago, LarsJ said: Why so complicated code? Because I was "grrr" . 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 November 27, 2018 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
argumentum Posted November 27, 2018 Author Share Posted November 27, 2018 (edited) Thanks a million @LarsJ. All that was missing was the GUISetState(@SW_SHOW) at the time of showing the context menu =D expandcollapse popup#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 November 27, 2018 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now