Jump to content
dts256

Popup Menus using labels

Recommended Posts

I'm trying to create my own menu system using labels but I'm having a problem with the recursion.

I've got code code that works for menu items, ie runs the selected program, but the problem is with the submenus. When a submenumenu is highlighted, the new submenu is created, but control passes to that submenu. This shouldn't happen until the mouse is over the new submenu. Also lose the current highlighted submenu item when the new menu is created. I suspect that the fix will solve both of these at the same time.

Another thing is that submenu's aren't deleted when moving the mouse to the previous menu.

I'm not sure how to unwind the recursion to achieve these.

Any help or pointers on how to progress this would be appreciated.

Thank you in advance for any help.

dts256

 

#include <GUIConstantsEx.au3> ;Constants for GUI Events
#include <File.au3>
#include <Array.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>

; Hides tray icon
#NoTrayIcon

$White = "0xFFFFFF"
$Green = "0x00FF00"
$sMenuFile = @ScriptDir & "\MenuTest.txt"

Global $aMenu
_FileReadToArray($sMenuFile, $aMenu, 1, ",")

_ArrayColInsert($aMenu, 0)                                      ; Add col 0 so array contents start in col 1
ReDim $aMenu[UBound($aMenu)][UBound($aMenu, 2) + 2]             ; Add 2 cols to the menu array

$Width = 400
$Height = 430

; create the GUI.
$MainWin = GUICreate("Program Launcher (Test)", $Width, $Height)

;Create the "Menu" button
$bMenu = GUICtrlCreateButton("Menu", 10, 190)   ; $Height - 50)

;Create the OK button
$okButton = GUICtrlCreateButton("OK", $Width - 80, $Height - 50)

;Create the Cancel button
$bCancel = GUICtrlCreateButton("Cancel", $Width - 50, $Height - 50)

;Show the GUI
GUISetState(@SW_SHOW)


;Continous loop to check for GUI events
while 1
   $msg = GUIGetMsg()

   Select
      Case $msg = $GUI_EVENT_CLOSE
         Exit
      Case $msg = $bCancel
         Exit
      Case $msg = $okButton
         Exit
      Case $msg = $bMenu
         $aMenuPos = CalcMenuPos($MainWin, $bMenu)
         $xPosMenu = $aMenuPos[0]
         $yPosMenu = $aMenuPos[1]

         $hMenu = CreateMenu("Root", $xPosMenu, $yPosMenu)
   EndSelect
WEnd

Func CreateMenu($sParentMenu, $XposMenu = -1, $yPosMenu = -1)
   $MenuWidth = 200
   $MenuHeight = 200

   $hPopupMenu = GUICreate("", $MenuWidth, $MenuHeight, $XposMenu, $YposMenu, BitOr($WS_POPUP, $WS_BORDER))
   GUISetBkColor($White, $hPopupMenu)

   BuildMenu($sParentMenu)

   GUISetState(@SW_SHOW, $hPopupMenu)


   while 1
      $aMsg = GUIGetMsg(1)

      $MouseOverCid = GetHighlightedMenuItem($hPopupMenu)

      Switch $aMsg[1]                                                                   ; Switch on window
         Case $MainWin                                                          ; Event is from Main window
            Select
               Case $aMsg[0] = $GUI_EVENT_CLOSE
                  Exit
               Case $aMsg[0] = $bCancel
                  Exit
               Case $aMsg[0] = $okButton
                  Exit
               Case $aMsg[0] = $bMenu
                  CreateMenu("Root")
            EndSelect

         Case $hPopupMenu                                                       ; Event is from popup menu
            For $Row = 1 To UBound($aMenu) - 1
               $MenuLabelCid = $aMenu[$Row][5]
               $sMenuId = $aMenu[$Row][4]

               If $sMenuID = Chr(0) Then                                                ; Program
                  If $aMsg[0] = $MenuLabelCid Then                                  ; Program Item Clicked
                     $sFilePath = $aMenu[$Row][3]
                     $WD = FileGetParent($sFilePath)

                     GUIDelete($hPopupMenu)
                     ShellExecute($sFilePath, "", $WD)

                     ExitLoop 2
                   ;  Return
                  EndIf
               EndIf

               If $sMenuID <> Chr(0) Then                                           ; Submenu
                  If $MouseOverCid = $MenuLabelCid And $MouseOverCid <> 0 Then
                     $aMenuPos = CalcMenuPos($hPopupMenu, $MenuLabelCid)
                     $xPosMenu = $aMenuPos[0]
                     $yPosMenu = $aMenuPos[1]

                     $hPopupMenu = CreateMenu($sMenuID, $xPosMenu, $yPosMenu)
                     GUIDelete($hPopupMenu)

                     ExitLoop 2
                     ;Return
                  EndIf
               EndIf
            Next
      EndSwitch
   wend
EndFunc ; CreateMenu

Func BuildMenu($sParentMenu)
   $LabelWidth = 100
   $LabelHeight = 20

   $MenuRow = 0
   For $row = 1 To UBound($aMenu) - 1
      $sParent = $aMenu[$row][1]

      If $sParentMenu = $sParent Then
         $sMenuItemText = $aMenu[$row][2]

         $MenuRow = $MenuRow + 1
         $aMenu[$row][5] = GUICtrlCreateLabel($sMenuItemText, 0, ($MenuRow * $LabelHeight) - $LabelHeight, $LabelWidth, $LabelHeight)

         $sMenuId = $aMenu[$row][4]
         If $sMenuID <> Chr(0) Then
            $sSM_char = ChrW(9654)
            $SM_char_Width = 8
            $aMenu[$row][6] = GUICtrlCreateLabel($sSM_char, $LabelWidth + 8, ($MenuRow * $LabelHeight) - $LabelHeight, $SM_char_Width, $LabelHeight, $SS_Right)
         Else
            $aMenu[$row][6] = $aMenu[$row][5]
         EndIf
      EndIf
   Next
EndFunc ; BuildMenu

Func GetHighlightedMenuItem($hMenu)
   Static $prevMouseOverCid = -9999

      $aMouseInfo = GUIGetCursorInfo($hMenu)
      $MouseOverCid = $aMouseInfo[4]

               If $MouseOverCid <> $prevMouseOverCid Then
                  GUICtrlSetBkColor($MouseOverCid, $Green)
                  GUICtrlSetBkColor($prevMouseOverCid, $White)

                  $prevMouseOverCid = $MouseOverCid
               EndIf

   Return $MouseOverCid
EndFunc ; GetHighlightedMenuItem

Func CalcMenuPos($hPopupMenu, $ControlID)
   $aPopupMenuPos = WinGetPos($hPopupMenu)                                          ; Get the popup menu pos
   $XposPopupMenu = $aPopupMenuPos[0]
   $YposPopupMenu = $aPopupMenuPos[1]

   $aLabelPos = ControlGetPos($hPopupMenu, "", $ControlID)                          ; Get the label pos
   $XposLabel = $aLabelPos[0]
   $yPosLabel = $aLabelPos[1]
   $LabelWidth = $aLabelPos[2]

   $xPosNewMenu = $XposPopupMenu + $XposLabel + $LabelWidth                         ; Get the new menu xPos
   $yPosNewMenu = $YposPopupMenu + $yPosLabel                                       ; Get the new menu yPos

   Local $aTempNewMenuPos[2]
   $aTempNewMenuPos[0] = $xPosNewMenu
   $aTempNewMenuPos[1] = $yPosNewMenu

   Return $aTempNewMenuPos
EndFunc ; CalcMenuPos

Func FileGetParent($sFilePath)
   Local $sParent
   Local $aElements = StringSplit($sFilePath, "\")

   For $x = 1 To UBound($aElements) - 2
      $sParent = $sParent & $aElements[$x] & "\"
   Next

   $sParent = StringTrimRight($sParent, "\")
   If StringLeft($sParent, 1) = '"' Then $sParent = $sParent & '"'

   Return $sParent
EndFunc ; FileGetParent

 

and here's the contents of the menutest.txt file

Root,Calculator,C:\Windows\System32\Calc.exe,
Root,RegEdit,C:\Windows\Regedit.exe,
Root,File Explorers,,File Explorers
File Explorers,Event Viewer,C:\Windows\System32\EventVwr.exe,
Root,System Restore,C:\Windows\System32\Rstrui.exe,
Root,Snipping Tool,C:\Windows\System32\SnippingTool.exe,
Root,Sound Recorder,C:\Windows\System32\SoundRecorder.exe,
Root,Task Manager,C:\Windows\System32\TaskMgr.exe,
File Explorers,Accessories,,Accessories
Accessories,Notepad,C:\Windows\System32\NotePad,

 

Share this post


Link to post
Share on other sites
Posted (edited)

Personally I'd create another array to hold all of the GUIs (sub-menus). Then you can programatically delete them as you go on. I do this with never-ending GUI's which expand depending on what data they're fed. I just swap your guis for controls in my scenario :)

 

Just a QnD example:

#include <GUIConstantsEx.au3> ;Constants for GUI Events
#include <File.au3>
#include <Array.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>

; Hides tray icon
#NoTrayIcon

$White = "0xFFFFFF"
$Green = "0x00FF00"
$sMenuFile = @ScriptDir & "\MenuTest.txt"
Global $aSubMenus[1] ; <---------------------------------------------------------------------- Creaete Global array to hold submenus
Global $aMenu
_FileReadToArray($sMenuFile, $aMenu, 1, ",")

_ArrayColInsert($aMenu, 0)                                      ; Add col 0 so array contents start in col 1
ReDim $aMenu[UBound($aMenu)][UBound($aMenu, 2) + 2]             ; Add 2 cols to the menu array

$Width = 400
$Height = 430

; create the GUI.
$MainWin = GUICreate("Program Launcher (Test)", $Width, $Height)

;Create the "Menu" button
$bMenu = GUICtrlCreateButton("Menu", 10, 190)   ; $Height - 50)

;Create the OK button
$okButton = GUICtrlCreateButton("OK", $Width - 80, $Height - 50)

;Create the Cancel button
$bCancel = GUICtrlCreateButton("Cancel", $Width - 50, $Height - 50)

;Show the GUI
GUISetState(@SW_SHOW)


;Continous loop to check for GUI events
while 1
   $msg = GUIGetMsg()

   Select
      Case $msg = $GUI_EVENT_CLOSE
         Exit
      Case $msg = $bCancel
         Exit
      Case $msg = $okButton
         Exit
      Case $msg = $bMenu
         $aMenuPos = CalcMenuPos($MainWin, $bMenu)
         $xPosMenu = $aMenuPos[0]
         $yPosMenu = $aMenuPos[1]

         $hMenu = CreateMenu("Root", $xPosMenu, $yPosMenu)
   EndSelect
WEnd

Func CreateMenu($sParentMenu, $XposMenu = -1, $yPosMenu = -1)
   $MenuWidth = 200
   $MenuHeight = 200

   _ArrayAdd($aSubMenus, GUICreate("", $MenuWidth, $MenuHeight, $XposMenu, $YposMenu, BitOr($WS_POPUP, $WS_BORDER), -1, $MainWin)) ; <------------------------------- add element (gui handle)

   GUISetBkColor($White, $aSubMenus[UBound($aSubMenus) - 1])

   BuildMenu($sParentMenu)

   GUISetState(@SW_SHOW, $aSubMenus[UBound($aSubMenus) - 1])


   while 1
      $aMsg = GUIGetMsg(1)

      $MouseOverCid = GetHighlightedMenuItem($aSubMenus[UBound($aSubMenus) - 1])

      Switch $aMsg[1]                                                                   ; Switch on window
         Case $MainWin                                                          ; Event is from Main window
            Select
               Case $aMsg[0] = $GUI_EVENT_CLOSE
                  Exit
               Case $aMsg[0] = $bCancel
                  Exit
               Case $aMsg[0] = $okButton
                  Exit
               Case $aMsg[0] = $bMenu
                  CreateMenu("Root")
            EndSelect

         Case $aSubMenus[UBound($aSubMenus) - 1]                                                       ; Event is from popup menu
            For $Row = 1 To UBound($aMenu) - 1
               $MenuLabelCid = $aMenu[$Row][5]
               $sMenuId = $aMenu[$Row][4]

               If $sMenuID = Chr(0) Then                                                ; Program
                  If $aMsg[0] = $MenuLabelCid Then                                  ; Program Item Clicked
                     $sFilePath = $aMenu[$Row][3]
                     $WD = FileGetParent($sFilePath)

                     For $i = UBound($aSubMenus) - 1 To 1 Step -1 ; <------------------------------------------------- delete them as you wish
                         GUIDelete($aSubMenus[$i])
                         _ArrayDelete($aSubMenus, $i)
                     Next

                     ShellExecute($sFilePath, "", $WD)

                     ExitLoop 2
                   ;  Return
                  EndIf
               EndIf

               If $sMenuID <> Chr(0) Then                                           ; Submenu
                  If $MouseOverCid = $MenuLabelCid And $MouseOverCid <> 0 Then
                     $aMenuPos = CalcMenuPos($aSubMenus[UBound($aSubMenus) - 1], $MenuLabelCid)
                     $xPosMenu = $aMenuPos[0]
                     $yPosMenu = $aMenuPos[1]

                     $hPopupMenu = CreateMenu($sMenuID, $xPosMenu, $yPosMenu)
                     ExitLoop 2
                     ;Return
                  EndIf
               EndIf
            Next
      EndSwitch
   wend
EndFunc ; CreateMenu


Func BuildMenu($sParentMenu)
   $LabelWidth = 100
   $LabelHeight = 20

   $MenuRow = 0
   For $row = 1 To UBound($aMenu) - 1
      $sParent = $aMenu[$row][1]

      If $sParentMenu = $sParent Then
         $sMenuItemText = $aMenu[$row][2]

         $MenuRow = $MenuRow + 1
         $aMenu[$row][5] = GUICtrlCreateLabel($sMenuItemText, 0, ($MenuRow * $LabelHeight) - $LabelHeight, $LabelWidth, $LabelHeight)

         $sMenuId = $aMenu[$row][4]
         If $sMenuID <> Chr(0) Then
            $sSM_char = ChrW(9654)
            $SM_char_Width = 8
            $aMenu[$row][6] = GUICtrlCreateLabel($sSM_char, $LabelWidth + 8, ($MenuRow * $LabelHeight) - $LabelHeight, $SM_char_Width, $LabelHeight, $SS_Right)
         Else
            $aMenu[$row][6] = $aMenu[$row][5]
         EndIf
      EndIf
   Next
EndFunc ; BuildMenu

Func GetHighlightedMenuItem($hMenu)
   Static $prevMouseOverCid = -9999

      $aMouseInfo = GUIGetCursorInfo($hMenu)
      $MouseOverCid = $aMouseInfo[4]

               If $MouseOverCid <> $prevMouseOverCid Then
                  GUICtrlSetBkColor($MouseOverCid, $Green)
                  GUICtrlSetBkColor($prevMouseOverCid, $White)

                  $prevMouseOverCid = $MouseOverCid
               EndIf

   Return $MouseOverCid
EndFunc ; GetHighlightedMenuItem

Func CalcMenuPos($hPopupMenu, $ControlID)
   $aPopupMenuPos = WinGetPos($hPopupMenu)                                          ; Get the popup menu pos
   $XposPopupMenu = $aPopupMenuPos[0]
   $YposPopupMenu = $aPopupMenuPos[1]

   $aLabelPos = ControlGetPos($hPopupMenu, "", $ControlID)                          ; Get the label pos
   $XposLabel = $aLabelPos[0]
   $yPosLabel = $aLabelPos[1]
   $LabelWidth = $aLabelPos[2]

   $xPosNewMenu = $XposPopupMenu + $XposLabel + $LabelWidth                         ; Get the new menu xPos
   $yPosNewMenu = $YposPopupMenu + $yPosLabel                                       ; Get the new menu yPos

   Local $aTempNewMenuPos[2]
   $aTempNewMenuPos[0] = $xPosNewMenu
   $aTempNewMenuPos[1] = $yPosNewMenu

   Return $aTempNewMenuPos
EndFunc ; CalcMenuPos

Func FileGetParent($sFilePath)
   Local $sParent
   Local $aElements = StringSplit($sFilePath, "\")

   For $x = 1 To UBound($aElements) - 2
      $sParent = $sParent & $aElements[$x] & "\"
   Next

   $sParent = StringTrimRight($sParent, "\")
   If StringLeft($sParent, 1) = '"' Then $sParent = $sParent & '"'

   Return $sParent
EndFunc ; FileGetParent

Look for the <------------------------------------------ lines. Everything else is how you left it (just realised I lied here, I removed the GUIDelete on line 114 of your original script)

 

Looks like you're on a fun little project

Edited by Inpho
More data

Share this post


Link to post
Share on other sites
On 5/13/2019 at 11:41 PM, dts256 said:

Another thing is that submenu's aren't deleted when moving the mouse to the previous menu.

GUIRegisterMsg will be needed for this.

Share this post


Link to post
Share on other sites

Hi @Inpho,

I attempted to do something similar by using  a separate array of submenus, but failed miserably, where you succeeded.  Thank you very much,

Now onto getting the submenu's to delete when moving the mouse to the previous menu. I'd prefer to do this without using GUIRegisterMsg. Would be  it possible, using the submenu array and setting the current submenu from the mouse position, then deleting any submenus after that one in the array, or by a similar sort of process ?

I've already written a function that can tell when the mouse is over a particular window,  just not sure yet how to incorporate it into the existing code.

Many thanks for your help so far.

Share this post


Link to post
Share on other sites

Very possible, although sounds like high maintenance if you ever want to add anything. I'd go for GuiRegisterMsg personally as it won't rely on any co-ordinates; it'd just respond to (e.g.) the WM_NCMOUSELEAVE Windows Message whenever the mouse cursor leaves the "current" gui and goes back to a parent one.

Unfortunately it's outside of my expertise, would love for a pro to chime in please.

Share this post


Link to post
Share on other sites

Hi @Inpho

I was thinking something along the lines of the folowing:

 

If UBound($aSubMenus) >= 3 Then
        For $Row = 1 To UBound($aSubMenus)
            If WinActive($aSubMenus[$Row] Then
            $hCurrMenu = $aSubmenus[$Row - 2]
            ExitLoop
            EndIf
        Next
   EndIf
   
   WinActivate($hCurrMenu)

and go from there.

I already know which label the mouse is over, so "re-highlight" it, make it the current selected item and continue with the main while loop.

Not worked it all out fully yet, just making this up as I'm typing so might not be quite right, but hopefully enough for you get the idea.

I'm aware that this code can be shortened by moving the WinActivate into the loop.

Am I on the right sort of lines with this ?

Share this post


Link to post
Share on other sites

I've made some good progress with this over the last few days and it's now at least partially working.

Major change is that i've split the CreateMenu function into CreateMenu and TrackMenu functions. I've also made some other changes here and there, main one being, just making submenus blue and commenting out the code for the submenu pointer label as it's not really needed at the moment and can easily be uncommented later.

It works for the root level menu and when moving the mouse back from the first level submenu to the root menu. However, when a 2nd level submenu is created, moving the mouse to the item on this menu deletes the 1st level submenu. I understand why it's doing this, but not sure how to modify my code to make it work properly.

Also it keeps re-creating the submenu when a submenu item is highlighted. Again I'm not sure how to stop this from happening.

I've created some additional functions that I thought might be useful but I'm unsure how to incorporate them into my script. These are clearly identified at the end of the script.

Any kind experts out there willing to take a look at my code and maybe suggest how it might be made to work.

 

#include <GUIConstantsEx.au3> ;Constants for GUI Events
#include <File.au3>
#include <Array.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>

; Hides tray icon
#NoTrayIcon

$White = "0xFFFFFF"
$Green = "0x00FF00"
$Red = "0xFF0000"
$Blue = "0x0000FF"

$sMenuFile = @ScriptDir & "\Menu.txt"
Global $aSubMenus[1][1 + 3]
; 1 = handle to the menu window
; 2 = ParentMenuID
; 3 = ActiveMenu ?
;

Global $aMenu
_FileReadToArray($sMenuFile, $aMenu, 1, ",")

_ArrayColInsert($aMenu, 0)                                      ; Add col 0 so array contents start in col 1
ReDim $aMenu[UBound($aMenu)][UBound($aMenu, 2) + 2]             ; Add 2 cols to the menu array

; 1 = ParentMenu
; 2 = MenuItem Text
; 3 = Program/File
; 4 = MenuID
; 5 = Label Cid
; 6 = Submenu pointer label Cid



$Width = 400
$Height = 430

; create the GUI.
$MainWin = GUICreate("Program Launcher (Test)", $Width, $Height)

;Create the "Menu" button
$bMenu = GUICtrlCreateButton("Menu", 10, 190)   ; $Height - 50)

;Create the OK button
$okButton = GUICtrlCreateButton("OK", $Width - 80, $Height - 50)

;Create the Cancel button
$bCancel = GUICtrlCreateButton("Cancel", $Width - 50, $Height - 50)


;Show the GUI
GUISetState(@SW_SHOW)


;Continous loop to check for GUI events
while 1
   $msg = GUIGetMsg()

   Select
      Case $msg = $GUI_EVENT_CLOSE
         Exit
      Case $msg = $bCancel
         Exit
      Case $msg = $okButton
         Exit
      Case $msg = $bMenu
         $aMenuPos = CalcMenuPos($MainWin, $bMenu)
         $xPosMenu = $aMenuPos[0]
         $yPosMenu = $aMenuPos[1]

         $hMenu = CreateMenu("Root", $xPosMenu, $yPosMenu)
         TrackMenu($hMenu)
   EndSelect
WEnd


Func CreateMenu($sParentMenu, $XposMenu = -1, $yPosMenu = -1)
   $MenuWidth = 200
   $MenuHeight = 200

;   _ArrayAdd($aSubMenus, GUICreate("", $MenuWidth, $MenuHeight, $XposMenu, $YposMenu, BitOr($WS_POPUP, $WS_BORDER), -1, $MainWin))

   _ArrayAdd($aSubmenus, "")
   $aSubmenus[UBound($aSubmenus) - 1][1] = GUICreate("", $MenuWidth, $MenuHeight, $XposMenu, $YposMenu, BitOr($WS_POPUP, $WS_BORDER), -1, $MainWin)
   $aSubmenus[UBound($aSubmenus) - 1][2] = $sParentMenu

   GUISetBkColor($White, $aSubMenus[UBound($aSubMenus) - 1][1])

   BuildMenu($sParentMenu)

   GUISetState(@SW_SHOW, $aSubMenus[UBound($aSubMenus) - 1][1])

   Return $aSubmenus[UBound($aSubmenus) - 1][1]
EndFunc ; CreateMenu



Func BuildMenu($sParentMenu)
   $LabelWidth = 200
   $LabelHeight = 20

   $MenuRow = 0
   For $row = 1 To UBound($aMenu) - 1
      $sParent = $aMenu[$row][1]

      If $sParentMenu = $sParent Then
         $sMenuItemText = $aMenu[$row][2]

         $MenuRow = $MenuRow + 1

         $sMenuId = $aMenu[$row][4]

         If $sMenuID = "" Then
            $aMenu[$row][5] = GUICtrlCreateLabel($sMenuItemText, 0, ($MenuRow * $LabelHeight) - $LabelHeight, $LabelWidth, $LabelHeight)
            $aMenu[$row][6] = $aMenu[$row][5]
         EndIf


         If $sMenuID <> "" Then
            $aMenu[$row][5] = GUICtrlCreateLabel($sMenuItemText, 0, ($MenuRow * $LabelHeight) - $LabelHeight, $LabelWidth - 8, $LabelHeight)

            $TempSubmenuCid = $aMenu[$row][5]
            GUICtrlSetColor($TempSubmenuCid, $Blue)


;            $sSM_char = ChrW(9654)
;            $SM_char_Width = 8
;            $aMenu[$row][6] = GUICtrlCreateLabel($sSM_char, $LabelWidth - 8 + 1, ($MenuRow * $LabelHeight) - $LabelHeight, $SM_char_Width, $LabelHeight, $SS_Right)
;         Else
            $aMenu[$row][6] = $aMenu[$row][5]
         EndIf
      EndIf
   Next
EndFunc ; BuildMenu

Func TrackMenu($hCurrMenu)
   while 1
      $aMsg = GUIGetMsg(1)

      Switch $aMsg[1]                                                                   ; Switch on window
         Case $MainWin                                                          ; Event is from Main window
            Select
               Case $aMsg[0] = $GUI_EVENT_CLOSE
                  Exit
               Case $aMsg[0] = $bCancel
                  Exit
               Case $aMsg[0] = $okButton
                  Exit
;               Case $aMsg[0] = $bMenu
;                  CreateMenu("Root")
            EndSelect

         Case $hCurrMenu    ;$aSubMenus[UBound($aSubMenus) - 1]                  ; Event is from popup menu
            If Not IsMouseOverWin($hCurrMenu) Then
               For $Row = 1 To UBound($aSubmenus) - 1
                  If IsMouseOverWin($aSubmenus[$Row][1]) Then
                     $hCurrMenu = $aSubmenus[$Row][1]
                     WinActivate($hCurrMenu)
                     TrackMenu($hCurrMenu)
                     ExitLoop
                  EndIf
               Next
            EndIf


            If IsMouseOverWin($hCurrMenu) Then
                  For $Row = UBound($aSubmenus) - 1 To 2 Step -1
                     If Not IsMouseOverWin($aSubmenus[$Row][1]) Then
                        GUIDelete($aSubMenus[$Row][1])
                        _ArrayDelete($aSubMenus, $Row)
                     EndIf
                  Next
            EndIf


            $MouseOverCid = GetCurrentMenuItem($hCurrMenu)      ;($aSubMenus[UBound($aSubMenus) - 1])

            For $Row = 1 To UBound($aMenu) - 1
               $MenuLabelCid = $aMenu[$Row][5]
               $sMenuId = $aMenu[$Row][4]

               If $sMenuID = "" Then                                                ; Program
                  If $aMsg[0] = $MenuLabelCid Then                                  ; Program Item Clicked
                     $sFilePath = $aMenu[$Row][3]
                     $WD = FileGetParent($sFilePath)

                     DeleteAllMenus()
                     ShellExecute($sFilePath, "", $WD)

                     ExitLoop 2
                   ;  Return
                  EndIf
               EndIf

               If $sMenuID <> "" Then                                           ; Submenu

                  If $MouseOverCid = $MenuLabelCid And $MouseOverCid <> 0 Then
                     Local $SubmenuCreated = False
                     For $x = 1 To UBound($aSubmenus) - 1
                        If $aSubmenus[$x][2] = $sMenuID Then
                           $SubmenuCreated = True
                           ExitLoop
                        EndIf
                     Next


                     Local $hNewSubMenu
                     If $SubmenuCreated = False Then
                        $aMenuPos = CalcMenuPos($aSubMenus[UBound($aSubMenus) - 1][1], $MenuLabelCid)
                        $xPosMenu = $aMenuPos[0]
                        $yPosMenu = $aMenuPos[1]

                        $hNewSubmenu = CreateMenu($sMenuID, $xPosMenu, $yPosMenu)
                        TrackMenu($hNewSubmenu)
                     EndIf
                  EndIf
               EndIf
            Next
      EndSwitch
   wend
EndFunc ; TrackMenu

Func DeleteAllMenus()
   For $Row = UBound($aSubMenus) - 1 To 1 Step -1
      GUIDelete($aMenu[$Row][7])
       _ArrayDelete($aMenu, $Row)

       GUIDelete($aSubMenus[$Row][1])                                           ; delete line
       _ArrayDelete($aSubMenus, $Row)                                           ; delete line
   Next
EndFunc ; DeleteAllMenus()

Func GetCurrentMenuItem($hMenuWin)
   Static $prevMouseOverCid = -9999

      $aMouseInfo = GUIGetCursorInfo($hMenuWin)
      $MouseOverCid = $aMouseInfo[4]

               If $MouseOverCid <> $prevMouseOverCid Then
                  GUICtrlSetBkColor($MouseOverCid, $Green)
                  GUICtrlSetBkColor($prevMouseOverCid, $White)

                  $prevMouseOverCid = $MouseOverCid
               EndIf

   Return $MouseOverCid
EndFunc ; GetCurrentMenuItem

Func CalcMenuPos($hPopupMenu, $ControlID)

;ConsoleWrite("CalcMenuPos - " & "$hPopupMenu is " & $hPopupMenu & "   $ControlID is " & $ControlID & @CRLF)

   $aPopupMenuPos = WinGetPos($hPopupMenu)                                          ; Get the popup menu pos
   $XposPopupMenu = $aPopupMenuPos[0]
   $YposPopupMenu = $aPopupMenuPos[1]

   $aLabelPos = ControlGetPos($hPopupMenu, "", $ControlID)                          ; Get the label pos
   $XposLabel = $aLabelPos[0]
   $yPosLabel = $aLabelPos[1]
   $LabelWidth = $aLabelPos[2]

;   $xPosNewMenu = $XposPopupMenu + $XposLabel + $LabelWidth                         ; Get the new menu xPos
   $xPosNewMenu = $XposPopupMenu + $XposLabel + 200
   $yPosNewMenu = $YposPopupMenu + $yPosLabel                                       ; Get the new menu yPos

   Local $aTempNewMenuPos[2]
   $aTempNewMenuPos[0] = $xPosNewMenu
   $aTempNewMenuPos[1] = $yPosNewMenu

   Return $aTempNewMenuPos
EndFunc ; CalcMenuPos



Func IsMouseOverWin($hWin)
   $MouseXpos = MouseGetPos(0)                                              ; Get Mouse X pos
   $MouseYPos = MouseGetPos(1)                                              ; Get Mouse Y pos


   $aWinPos = WinGetPos($hWin)                                          ; Get the window info

   $XposWin = $aWinPos[0]
   $YposWin = $aWinPos[1]
   $WidthWin = $aWinPos[2]
   $HeightWin = $aWinPos[3]


   Local $MouseIsOverWin = False

   If $MouseXpos > $XposWin And _
      $MouseYpos >  $YposWin And _
      $MouseXpos < $XposWin + $WidthWin And _
      $MouseYPos < $YposWin  + $HeightWin Then

      $MouseIsOverWin = True
   EndIf

   Return $MouseIsOverWin
EndFunc ; IsMouseOverWin



Func FileGetParent($sFilePath)
   Local $sParent
   Local $aElements = StringSplit($sFilePath, "\")

   For $x = 1 To UBound($aElements) - 2
      $sParent = $sParent & $aElements[$x] & "\"
   Next

   $sParent = StringTrimRight($sParent, "\")
   If StringLeft($sParent, 1) = '"' Then $sParent = $sParent & '"'

   Return $sParent
EndFunc ; FileGetParent



; **************************************************
; Additional functions that may prove useful
; Apart from GetActiveWinHandle() these are untested

Func GetPrevMenuHandle($hCurrMenu)
   Local $hTempPrevMenu
   For $Row = 1 To UBound($aSubmenus) - 1
      If $hCurrMenu = $aSubmenus[$Row][1] Then
         $hTempPrevMenu = $aSubmenus[$Row[1]
         ExitLoop
      EndIf
   Next

   Return $hTempPrevMenu
EndFunc ; GetPrevMenuHandle


Func GetActiveWinHandle()
   $TempWinHandle = WinGetHandle("[ACTIVE]")
   Return $TempWinHandle
EndFunc ; GetActiveWinHandle


Func DeleteAllMenusAfter($hMenuWin)
   For $Row = 1 To UBound($aSubmenus) -1
      If $hMenuWin = $aSubMenus[Row][1] Then

         For $Row2 = UBound($aSubmenus) -1 To $Row + 1
            GUIDelete($aSubMenus[$Row][1])
            _ArrayDelete($aSubMenus, $Row)
            ExitLoop
         Next
      EndIf
   Next
EndFunc ; DeleteAllMenusAfter


Func DeleteMenu($hMenuWin)
   For $Row = 1 To UBound($aSubmenus) -1
      If $hMenuWin = $aSubMenus[Row][1] Then
         GUIDelete($aSubMenus[$Row][1])
         _ArrayDelete($aSubMenus, $Row)
         ExitLoop
      EndIf
   Next
EndFunc ; DeleteMenu

 

 

Share this post


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

×
×
  • Create New...