Jump to content

Context menu in ListView


 Share

Recommended Posts

This is the following of a discussion we're having with Lion66 in LarsJ's thread.
As the "light" script below isn't related to Virtual Listview any more, then it's better to create a new thread for this example.

2 basic functionalities :
* Right-click on LV rows to display a context menu
* Right-click on LV headers to switch from 1 column to the other (the "searched" column and its orange marker in other scripts)

@Lion66 you can pick some parts of the code below (the ones related to the LV context menu) and adapt them to :
* the incremental search scripts in Virtual listviews, with colored matches, found in LarsJ's thread.
* or simply adapt them to your own scripts :)

#include <ComboConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiMenu.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1)
Opt("GuiCloseOnESC", 0)

Global $g_iRows = 1000, $g_iCols = 6, $g_iLeftLV = 10, $g_iTopLV = 40, $g_hGui, $g_hListView, $g_hHeader
Global $g_aCols = ["Col 0", "Col 1", "Col 2", "Col 3", "Col 4", "Col 5"], $g_aWidths = [230, 61, 124, 70, 60, 60]
Global $g_idListView, $g_idMarker, $g_idComboCol, $g_idComboColDummy, $g_iSearchCol
Global $g_idContextDummy, $g_hContextmenu, $g_iItem = -1, $g_iSubItem = -1

Example()

Func Example()
  ; Create GUI
  $g_hGui = GUICreate("Context menu in LV (not in headers)", 630+20, 582+30+20)

  ; Create Edit control (search) + dummy control
  Local $idEdit = GUICtrlCreateEdit("", 120, 10, 305, 20, BitXOR($GUI_SS_DEFAULT_EDIT, $WS_HSCROLL, $WS_VSCROLL))

  ; Create ComboBox control (how to search : RegEx or Normal ?)
  Local $idSearchHow = GUICtrlCreateCombo("RegEx search", 11, 9, 100, 20, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_DROPDOWNLIST))
  Local $sSearchHow = "RegEx search"
  GUICtrlSetData($idSearchHow, "Normal search", $sSearchHow)

  ; Create ComboBox control (column where to search) + dummy control
  GUICtrlCreateLabel("Col", 429, 10, 20, 20, BitOR($SS_CENTERIMAGE, $SS_CENTER))
  $g_idComboCol = GUICtrlCreateCombo("0", 452, 9, 41, 20, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_DROPDOWNLIST))
  $g_iSearchCol = 0 ; default column where to search (changeable)
  For $i = 1 To $g_iCols - 1
    GUICtrlSetData($g_idComboCol, $i & "|", $g_iSearchCol)
  Next
  $g_idComboColDummy = GUICtrlCreateDummy()

  ; Create Label control (number of matching results)
  Local $idResult = GUICtrlCreateLabel(" " & $g_iRows & " rows (no pattern)", 501, 10, 135, 20, BitOR($SS_CENTERIMAGE, $SS_SUNKEN))

  ; Create ListView
  $g_idListView = GUICtrlCreateListView( "", $g_iLeftLV, $g_iTopLV, 630, 582)
  $g_hListView = GUICtrlGetHandle($g_idListView)
  $g_hHeader = _GUICtrlListView_GetHeader($g_idListView)
  For $i = 0 To $g_iCols - 1
    _GUICtrlListView_AddColumn($g_idListView, $g_aCols[$i], $g_aWidths[$i])
  Next
  Local $sPrepareTxt
  For $i = 0 To $g_iRows - 1
    $sPrepareTxt = ""
    For $j = 0 To $g_iCols - 1
      $sPrepareTxt &= "R" & $i & "/C" & $j & "|"
    Next
    GUICtrlCreateListViewItem($sPrepareTxt, $g_idListview)
  Next

  ; Create Marker (an orange line placed above the header of the column being searched)
  $g_idMarker = GUICtrlCreateLabel("", 0, 0)
  GUICtrlSetBkColor(-1, 0xFFA060) ; orange
  _MoveMarker($g_iSearchCol)
  _GUICtrlListView_SetSelectedColumn($g_idListView, $g_iSearchCol)

 ; Create Context menu
  $g_idContextDummy = GUICtrlCreateDummy()
  Local $idContextMenu = GUICtrlCreateContextMenu($g_idContextDummy)
  Local $idContext1 = GUICtrlCreateMenuItem("Option 1", $idContextMenu)
  Local $idContext2 = GUICtrlCreateMenuItem("Option 2", $idContextMenu)
  Local $idContext3 = GUICtrlCreateMenuItem("Option 3", $idContextMenu)
  $g_hContextMenu = GuiCtrlGetHandle($idContextMenu)

  GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
  GUISetState(@SW_SHOW)

  While 1
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop

      Case $g_idComboCol, $g_idComboColDummy
        $g_iSearchCol = GUICtrlRead($g_idComboCol)
        _MoveMarker($g_iSearchCol)
        _GUICtrlListView_SetSelectedColumn($g_hListView, $g_iSearchCol)

      Case $g_idContextDummy
        _GUICtrlListView_SetSelectedColumn($g_hListView, $g_iSubItem)
        Local $iMenu_Choice = _TrackPopupMenu($g_hContextMenu, $g_hGui, MouseGetPos(0), MouseGetPos(1))
        If $iMenu_Choice Then
          Switch $iMenu_Choice
            Case $idContext1
              ConsoleWrite("Code for Option 1" & @lf)
            Case $idContext2
              ConsoleWrite("Code for Option 2" & @lf)
            Case $idContext3
              ConsoleWrite("Code for Option 3" & @lf)
          EndSwitch
          Local $sTextMenu = _GUICtrlMenu_GetItemText($g_hContextmenu, $iMenu_Choice, False)
          Local $sTextLV = _GUICtrlListView_GetItemText($g_hListView, $g_iItem, $g_iSubItem)
          MsgBox($MB_TOPMOST, $sTextMenu, "Row = " & $g_iItem & "   Column = " & $g_iSubItem & "   Text = " & $sTextLV & @lf)
        Else
          ConsoleWrite("Context menu cancelled by user" & @lf)
        Endif

      Case $GUI_EVENT_RESTORE ; needed, or Marker goes back in 0, 0 after Restore (why ?)
        _MoveMarker($g_iSearchCol)
    EndSwitch
  WEnd

  ; Cleanup
  GUIDelete($g_hGui)
EndFunc   ;==>Example

;========================================================================
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

  Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
  Switch HWnd(DllStructGetData($tNMHDR, "hWndFrom"))

    Case $g_hListView
      Switch DllStructGetData($tNMHDR, "Code")
        Case $NM_RCLICK
          Local $tInfo = DllStructCreate($tagNMITEMACTIVATE, $lParam)
          $g_iItem = DllStructGetData($tInfo, "Index")
          If $g_iItem > -1 Then ; valid row
              $g_iSubItem = DllStructGetData($tInfo, "SubItem")
              GUICtrlSendToDummy($g_idContextDummy)
          EndIf
      EndSwitch

    Case $g_hHeader
      Switch DllStructGetData($tNMHDR, "Code")
        Case $HDN_ENDTRACKW, $HDN_DIVIDERDBLCLICKW ; let's forget $HDN_TRACKW...
          _MoveMarker(GUICtrlRead($g_idComboCol))

        Case $NM_RCLICK
          Local $aHit = _GUICtrlListView_SubItemHitTest($g_hListView)
          ; $aHit[1] : 0-based index of the LV subitem... i.e. the column in our case (may be -1 if right click on empty part of header)
          If $aHit[1] > - 1 Then ; valid column
            GUICtrlSetData($g_idComboCol, $aHit[1])
            GUICtrlSendToDummy($g_idComboColDummy)
          EndIf
      EndSwitch
  EndSwitch

  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

;========================================================================
Func _MoveMarker($iCol)

  Local $aRect = _GUICtrlHeader_GetItemRect($g_hHeader, $iCol)
  ControlMove($g_hGui, "", $g_idMarker, $g_iLeftLV + $aRect[0], $g_iTopLV - 3, $aRect[2] - $aRect[0] + 1, 3)
EndFunc   ;==>_MoveMarker

; =========================================================================================================================================
Func _TrackPopupMenu($hMenu, $hWnd, $iX, $iY)

    ; $TPM_RETURNCMD returns the menu item identifier of the user's selection in the return value.
    Return DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", $TPM_RETURNCMD, "int", $iX, "int", $iY, "hwnd", $hWnd, "ptr", 0)[0]
EndFunc   ;==>_TrackPopupMenu

Note : nothing is "searched" in this example, which is based on the creation of a LV context menu which doesn't interfere with LV headers.

Edited by pixelsearch
Link to comment
Share on other sites

The problem was solved:

I went back to using the function _GetText...

Instead _GUICtrlListView_GetItemText, as in the example.

It's time to come up with additional LV use options and solve them. 😄

Thank you.

 

Edited by Lion66
Link to comment
Share on other sites

4 hours ago, Lion66 said:

I went back to using the function _GetText...

I was sure you'd do that when I posted the script above, because I couldn't use Func _GetText() in it. The function includes arrays & structures that has nothing to do with this Context menu example, for instance :

$sGetText = $g_aSubArray[$g_tIndex.arr($iItem + 1)][$iSubItem]

A thought to @Nine who indicated this "structure way" a few weeks ago and all later scripts are based on it.

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