Jump to content

How to change state of context menu items


Go to solution Solved by Nine,

Recommended Posts

Posted

I have worked a lot with menus and changing states of items within those menus.

In this case, I am working with context menus and the items within them don't seem to want to change state after it's running. I can change state of a context menu item before GUISetState but not after.

In the docs, the info for GUICtrlSetState states the following:

Quote

State of a "contextmenu" control cannot be changed.

So that is something, of course. But to me, that refers to the whole contextmenu control and not to individual context menu entries. Besides, I can change the state of individual context menu entries as long as it is done before the GUI is running, just not after.

In this example, I made the hotkey Esc trigger the disabling of the "About button" on the OK button's context menu. But as can be seen when running the example, it does not disable the context menu item.

; right click on gui to bring up context Menu.
; right click on the "ok" button to bring up a controll specific context menu.

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>

Global $idMni_About

HotKeySet("{Esc}", "_disable")

Example()

Func Example()
    GUICreate("My GUI Context Menu", 300, 200)

    Local $idContextmenu = GUICtrlCreateContextMenu()

    Local $idMnu_Newsub = GUICtrlCreateMenu("new", $idContextmenu)
    Local $idMni_NewsubmenuText = GUICtrlCreateMenuItem("text", $idMnu_Newsub)

    Local $idButton = GUICtrlCreateButton("OK", 100, 100, 70, 20)
    Local $idCtx_Button = GUICtrlCreateContextMenu($idButton)
    Local $idMni_About = GUICtrlCreateMenuItem("About button", $idCtx_Button)

    Local $idMni_Open = GUICtrlCreateMenuItem("Open", $idContextmenu)
    Local $idMni_Save = GUICtrlCreateMenuItem("Save", $idContextmenu)
    GUICtrlCreateMenuItem("", $idContextmenu) ; separator

    Local $idMni_Info = GUICtrlCreateMenuItem("Info", $idContextmenu)

    GUISetState(@SW_SHOW)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd
    GUIDelete()
EndFunc   ;==>Example

Func _disable()
    GUICtrlSetState($idMni_About, $GUI_DISABLE)
    ConsoleWrite("Disable context menu item, please." & @CRLF)
EndFunc

 

Does anyone know of any tricks to change state of context menu items?

I just need basic enable/disable. Thank you. :)

  • Solution
Posted

There is a couple of issues with your code.  First you declare $idMni_About globally and then you declare it locally.  So global variable is null. 

Second, you cannot execute code while your script shows a context menu.  The hotkeyset is only executed after the context menu is closed.

Posted

S:

; right click on gui to bring up context Menu.
; right click on the "ok" button to bring up a controll specific context menu.

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
Opt('GUICloseOnESC', 0)
HotKeySet("{F8} ", "_Disable_MenuAbout")
HotKeySet("{F9} ", "_Enable_MenuAbout")
Global $hwnd, $idContextmenu, $idMnu_Newsub, $idMni_NewsubmenuText, $idButton, $idCtx_Button, $idMni_About, $idMni_Open, $idMni_Save, $idMni_Info
_GUICreate()

Func _GUICreate()
    $hwnd = GUICreate("My GUI Context Menu", 300, 200)
    $idContextmenu = GUICtrlCreateContextMenu()
    $idMnu_Newsub = GUICtrlCreateMenu("New", $idContextmenu)
    $idMni_NewsubmenuText = GUICtrlCreateMenuItem("Text", $idMnu_Newsub)
    $idButton = GUICtrlCreateButton("OK", 100, 100, 70, 20)
    $idCtx_Button = GUICtrlCreateContextMenu($idButton)
    $idMni_About = GUICtrlCreateMenuItem("About button", $idCtx_Button)
    $idMni_Open = GUICtrlCreateMenuItem("Open", $idContextmenu)
    $idMni_Save = GUICtrlCreateMenuItem("Save", $idContextmenu)
    GUICtrlCreateMenuItem("", $idContextmenu)     ; separator
    $idMni_Info = GUICtrlCreateMenuItem("Info", $idContextmenu)
    GUISetState(@SW_SHOW, $hwnd)
EndFunc   ;==>_GUICreate

; Loop until the user exits.
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $idButton, $idMni_About, $idMni_Open, $idMni_Save, $idMni_Info, $idMni_NewsubmenuText
            MsgBox(0, '', 'OK', 0, $hwnd)
    EndSwitch
WEnd
GUIDelete()

Func _Disable_MenuAbout()
    GUICtrlSetState($idMni_About, $GUI_DISABLE)
    ConsoleWrite("! Context menu item Disabled !" & @CRLF)
EndFunc   ;==>_Disable_MenuAbout

Func _Enable_MenuAbout()
    GUICtrlSetState($idMni_About, $GUI_ENABLE)
    ConsoleWrite("! Context menu item Enable!" & @CRLF)
EndFunc   ;==>_Enable_MenuAbout

 

Enjoy my work? Buy me a 🍻 or tip via ❤️ PayPal

Posted
4 hours ago, WildByDesign said:

In this case,

; right click on gui to bring up context Menu. DONE
; right click on the "ok" button to bring up a controll specific context menu. YOUR TURN TO CODE IT

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>

Global $idMni_About

;~ HotKeySet("{Esc}", "_disable")

Example()

Func Example()
    Local $hGui = GUICreate("My GUI Context Menu", 300, 200)
    Local $idContextmenu = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
    Local $idMnu_Newsub = GUICtrlCreateMenu("new", $idContextmenu)
    Local $idMni_NewsubmenuText = GUICtrlCreateMenuItem("text", $idMnu_Newsub)
    Local $idButton = GUICtrlCreateButton("on", 100, 100, 70, 20)
    Local $idMni_AboutCM = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
    Local $idMni_About = GUICtrlCreateMenuItem("About button", $idMni_AboutCM)
    Local $idMni_Open = GUICtrlCreateMenuItem("Open", $idContextmenu)
    Local $idMni_Save = GUICtrlCreateMenuItem("Save", $idContextmenu)
    GUICtrlCreateMenuItem("", $idContextmenu) ; separator
    Local $idMni_Info = GUICtrlCreateMenuItem("Info", $idContextmenu)
    GUISetState(@SW_SHOW)
    While 1 ; Loop until the user exits.
        Switch GUIGetMsg()
            Case $GUI_EVENT_SECONDARYUP
                $aCursorInfo = GUIGetCursorInfo($hGui)
                If @error Then ContinueLoop
                ConsoleWrite('- $GUI_EVENT_SECONDARYUP - ' & $aCursorInfo[4] & @CRLF)
                If UBound($aCursorInfo) = 5 And GUICtrlRead($idButton) = 'on' Then
                    Switch $aCursorInfo[4]
                        Case 0
                            TrackPopupMenu($hGui, GUICtrlGetHandle($idContextmenu), MouseGetPos(0), MouseGetPos(1))
                        Case Else ; ..you do your part too  =P
                            TrackPopupMenu($hGui, GUICtrlGetHandle($idMni_AboutCM), MouseGetPos(0), MouseGetPos(1))
                    EndSwitch
                EndIf
            Case $idButton
                If GUICtrlRead($idButton) = 'on' Then
                    GUICtrlSetData($idButton, 'off')
                Else
                    GUICtrlSetData($idButton, 'on')
                EndIf
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd
    GUIDelete()
EndFunc   ;==>Example

;~ Func _disable()
;~     GUICtrlSetState($idMni_About, $GUI_DISABLE)
;~     ConsoleWrite("Disable context menu item, please." & @CRLF)
;~ EndFunc

; 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)
        DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc   ;==>TrackPopupMenu

 

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

Posted
9 hours ago, Nine said:

There is a couple of issues with your code.  First you declare $idMni_About globally and then you declare it locally.  So global variable is null. 

Thank you for noticing my mistake of declaring it locally after having already declared it globally. That simple mistake was the problem. Small mistake but big consequences.

I've made that mistake a few times before and I paid the price for it every time. Let's hope this is the last time. :)

9 hours ago, Nine said:

Second, you cannot execute code while your script shows a context menu.  The hotkeyset is only executed after the context menu is closed.

This is good information that I was not aware of. I will have to keep this in mind.

Posted

Thank you @Trong for your example as well. It works very well. :)

Thanks @argumentum for your example too. I've done some scripts with _GUICtrlMenu_TrackPopupMenu before which is interesting and I assume is likely similar to what you've done with the DLLCall in the TrackMenuPopup function.

Although yours calls TrackPopupMenuEx while the other calls TrackPopupMenu. I'll dig into the MS docs because now I am curious. :)

By the way, I have never used dummy controls because but yet I've seen them used a good amount. What is the benefit of dummy controls?

Posted
34 minutes ago, WildByDesign said:

What is the benefit of dummy controls?

It pushes in the message pump in order.  So all messages are treated in the right sequence.  By using a global variable for example, it may shortcut some messages and produce unpredictable results.

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