Jump to content

Recommended Posts

Posted

I am trying to implement a context menu on listview item and came up with a code similar to the following. It seems OK except for one thing. If you right-click on the empty earea of the listview control immediately after the code is run, there is no response and that is what it should be. But once you right-click an item and the context menu is invoked, the context menu pops up even when you right-click on the empty area. How can I prevent this from happening?
 

#include <GUIConstants.au3>
#include <GUIListView.au3>

Global $winMain = GUICreate("Playlist", 400, 500, -1, -1, $WS_SIZEBOX)
GUISetFont(9, 400, "", "Arial", $winMain)
Global $ctrlView = GUICtrlCreateListView("File Names", 2, 2, 396, 450, _
        BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER, $LVS_REPORT, $LVS_SINGLESEL, $LVS_AUTOARRANGE), _
        BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES))

For $i = 1 To 9
    _GUICtrlListView_AddItem($ctrlView, "FilePath " & $i)
Next
_GUICtrlListView_SetColumnWidth($ctrlView, 0, 375)
GUISetState()
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

While 1
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
        ExitLoop


    EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $MsgID, $wParam, $lParam)
    #forceref $hWnd, $MsgID, $wParam, $lParam
    Local $tagNMHDR = DllStructCreate("int;int;int", $lParam)
    If @error Then Return $GUI_RUNDEFMSG
    Local $code = DllStructGetData($tagNMHDR, 3)
    If $code = $NM_RCLICK And _GUICtrlListView_GetSelectedIndices($ctrlView) <> "" Then
        $idContextmenu = GUICtrlCreateContextMenu($ctrlView)
        $idSubmenu1 = GUICtrlCreateMenuItem("Submenu 1", $idContextmenu)
        $idSubmenu2 = GUICtrlCreateMenuItem("Submenu 2", $idContextmenu)
        $idSubmenu3 = GUICtrlCreateMenuItem("Submenu 3", $idContextmenu)
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc


 

Posted

Here the way I would do it :

#include <GUIConstants.au3>
#include <GUIListView.au3>

Global $idContextmenu = 0, $idSubmenu1 = 999, $idSubmenu2 = 999, $idSubmenu3 = 999

Global $winMain = GUICreate("Playlist", 400, 500, -1, -1, $WS_SIZEBOX)
GUISetFont(9, 400, "", "Arial", $winMain)
Global $ctrlView = GUICtrlCreateListView("File Names", 2, 2, 396, 450, _
    BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER, $LVS_REPORT, $LVS_SINGLESEL, $LVS_AUTOARRANGE), _
    BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES))

For $i = 1 To 9
  _GUICtrlListView_AddItem($ctrlView, "FilePath " & $i)
Next
_GUICtrlListView_SetColumnWidth($ctrlView, 0, 375)
GUISetState()
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

While 1
  Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
      ExitLoop
    Case $idSubmenu1 To $idSubmenu3
      ConsoleWrite("submenu was selected" & @CRLF)

  EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $MsgID, $wParam, $lParam)
  #forceref $hWnd, $MsgID, $wParam
  Local $tagNMHDR = DllStructCreate("int;int;int", $lParam)
  If @error Then Return $GUI_RUNDEFMSG
  Local $code = DllStructGetData($tagNMHDR, 3)
  If $code = $NM_RCLICK Then
    If _GUICtrlListView_GetSelectedIndices($ctrlView) = "" Then
      GUICtrlDelete($idContextmenu)
      $idContextmenu = 0
    ElseIf Not $idContextmenu Then
      $idContextmenu = GUICtrlCreateContextMenu($ctrlView)
      $idSubmenu1 = GUICtrlCreateMenuItem("Submenu 1", $idContextmenu)
      $idSubmenu2 = GUICtrlCreateMenuItem("Submenu 2", $idContextmenu)
      $idSubmenu3 = GUICtrlCreateMenuItem("Submenu 3", $idContextmenu)
    EndIf
  EndIf
  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

 

Posted

@Nine, Thank you again. Your code works fine in actual situation as well. Here I have a coulpe of questions I would like to ask you. What is the wisdom of assigning initial values to submenu items?  What is the logic behind it? Should it be as big as 999 instead of just 1? I found that the code does weird things if they are not initialized with some values but I don't understand why. Another part I don't understand is 'ElseIf Not $idContextmenu'. Why does'nt simple 'Else' work? Please pardon my ignorance if these questions look silly. I started to learn coding at a late age and I am still learning. AutoIt has been a great friend of mine since my retirement and I thank you guys for maintaining this excellent  community.

Posted
  On 8/11/2020 at 10:22 AM, CYCho said:

What is the wisdom of assigning initial values to submenu items?

Expand  

If you don't then they will be equal to 0 and this is the value of GUIGetMsg : $GUI_EVENT_NONE.  So it will be triggered all the time. 

  On 8/11/2020 at 10:22 AM, CYCho said:

Another part I don't understand is 'ElseIf Not $idContextmenu'. Why does'nt simple 'Else' work?

Expand  

There is no need to recreate the context menu every time if it already exists.  Unless it has been deleted, you should keep the current one.  This is why I set $idContextMenu to 0 when I delete it.

Posted (edited)

One thing I forgot to tell you, if you keep recreating context menu, the script will start chomping memory. Eventually it may also crash out of memory.

Help file says :

  Quote

Only one context menu per control is possible. If you wish to create a new context menu one you have to delete the existing menu first.

Expand  

Did some more tests, and you must delete submenu items also, as they are not freed when you delete the menu.  It will continue to take memory otherwise :

GUICtrlDelete($idSubmenu1)
      GUICtrlDelete($idSubmenu2)
      GUICtrlDelete($idSubmenu3)
      GUICtrlDelete($idContextmenu)
      $idContextmenu = 0

 

Edited by Nine

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