Jump to content

Context menu on listview item


CYCho
 Share

Recommended Posts

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


 

Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

1 hour ago, CYCho said:

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

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. 

1 hour ago, CYCho said:

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

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.

Link to comment
Share on other sites

12 minutes ago, Nine said:

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. 

Your answers are simple but clear. I'm glad I was very close about the 2nd question. Thank you for your kind answers.

Link to comment
Share on other sites

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.

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