goss34

Search In ListView (Redraw with matching string)

11 posts in this topic

Hi Guys,

I am writing an app that involves a list view with for example 100 rows. I have added an input box and search button to search the list view for whatever was in the input box.

I found this function on the forum:

Button2()

Func Button2()
    ;MsgBox(0, "Button2", GUICtrlRead($Input))
    $value = GUICtrlRead($Input)
    ; Search for target item
    $iI = _GUICtrlListView_FindInText($ListView1, $value, -1)
    _GUICtrlListView_EnsureVisible($ListView1, $iI)
EndFunc

This works to a degree but only jumps to a matching string and not in every case even though the string is definitely in the list view.

What i want to do is redraw the listview with any results matching or part matching the string in the input box. 

Im sure someone will of already done this if so could i see the code as i do not know where to begin.

Thanks,

Dan

 

Share this post


Link to post
Share on other sites



Here is an example for filtering a LlistView

#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    Local $idListview, $idListview1, $aArr, $iNoCols = 10, $iNoItems = 100, $iDataLimit_0To = 5, $sFind, $aArrData[$iNoItems][$iNoCols]
    Local $sCols = "col0"
    GUICreate("ListView Original", 500, 350, 0, 0, $WS_SIZEBOX)
    GUICtrlCreateLabel("Filter", 4, 302)
    Local $idInput = GUICtrlCreateInput("2", 40, 302, 355, 25)
    Local $FilterBut = GUICtrlCreateButton("Go", 400, 302, 30, 25)
    For $m = 1 To $iNoCols - 1
        $sCols &= "|col" & $m
    Next
    $idListview = GUICtrlCreateListView($sCols, 0, 0, 500, 300)

    ; ------- Create data in array for ListView ------------------
    For $j = 0 To $iNoItems - 1
        $sData = "index " & $j
        $aArrData[$j][0] = $sData
        For $k = 1 To $iNoCols - 1
            $aArrData[$j][$k] = Random(0, $iDataLimit_0To, 1) & Random(0, $iDataLimit_0To, 1) & _
                    Random(0, $iDataLimit_0To, 1) & Random(0, $iDataLimit_0To, 1) & Random(0, $iDataLimit_0To, 1)
        Next
    Next
    _GUICtrlListView_AddArray($idListview, $aArrData)
    _GUICtrlListView_SetColumnWidth($idListview, 0, 55)
    GUISetState(@SW_SHOW)

    ; ------- Create 2nd GUI and ListView and fill with same data. ---------------
    GUICreate("ListView Filtered", 500, 330, @DesktopWidth / 2, 0, $WS_SIZEBOX)
    $idListview1 = GUICtrlCreateListView($sCols, 0, 0, 500, 300)
    _GUICtrlListView_AddArray($idListview1, $aArrData)
    _GUICtrlListView_SetColumnWidth($idListview1, 0, 55)
    GUISetState(@SW_SHOW)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                Exitloop
            Case $FilterBut
                $sFind = GUICtrlRead($idInput)
                If $sFind <> "" Then
                    _GUICtrlListView_DeleteAllItems($idListview1)
                    For $i = 0 To _GUICtrlListView_GetItemCount($idListview) - 1
                        $aArr = _GUICtrlListView_GetItemTextArray($idListview, $i)
                        $sData1 = ""
                        For $n = 1 To UBound($aArr) - 1
                            If StringInStr($aArr[$n], $sFind) = 0 Then $aArr[$n] = "---" ; <<<< Apply filter
                            $sData1 &= $aArr[$n] & "|"
                        Next
                        GUICtrlCreateListViewItem($sData1, $idListview1)
                    Next
                Else ; When no filter present.
                    _GUICtrlListView_DeleteAllItems($idListview1)
                    _GUICtrlListView_AddArray($idListview1, $aArrData)
                EndIf
        EndSwitch
    WEnd
    GUIDelete()
EndFunc   ;==>Example

 

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

goss34, You can find an example with a search field and a virtual listview here. Initially the listview is filled out with 1000 rows of random strings with a length between 10 and 30 characters.

When you type in a search string in the search field (edit control), the listview is updated with the rows, that matches the search string. The listview is updated dynamically while the search string is typed in. The search string can be a regular expression.

 

 

Edited by LarsJ

Share this post


Link to post
Share on other sites

Woah, thanks for the replies guys, i have just picked up the examples and trying to figure out what i need to amend my list view.

Be back once i have had time to work through them.

Thanks

Dan

Share this post


Link to post
Share on other sites

Hi Guys,

I am trying to follow LarsJ example but its going way over my skill level at the moment. 

Any chance someone could slim it down or comment it so i can try to understand what is actually going on.

I just made this reproducer quickly (haha not as quick as you might think) but its doing the same as i am doing in my script at the moment although the search works better with the simple strings it currently has! Maybe you could merge the 2 so i can grasp whats going on in the big example? (I do struggle to understand whats happening when arrays are involved).

#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <Array.au3>
#include <File.au3>
#include <ButtonConstants.au3>


Global $Fill = @ScriptDir & "\sample.ini"

IniWriteSection(@ScriptDir & "\sample.ini", "ITEM1", "1=2")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM2", "1=3")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM3", "1=4")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM4", "1=5")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM5", "1=6")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM6", "1=7")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM7", "1=8")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM8", "1=9")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM9", "1=10")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM10", "1=11")
IniWriteSection(@ScriptDir & "\sample.ini", "ITEM11", "1=12")

$Gui = GUICreate("Gui", 300, 250)
$LV = GUICtrlCreateListView("Item|Value", 18, 40, 260, 200)
_GUICtrlListView_SetExtendedListViewStyle($LV, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES))
GUICtrlSendMsg(-1, 0x101E, 0, 130)
GUICtrlSendMsg(-1, 0x101E, 1, 125)
;GUICtrlCreateTabItem("") ; This ends the tab item creation
$Button2 = GUICtrlCreateButton("Search", 180, 10, 100, 22, 0)
$Input = GUICtrlCreateInput("Enter Search Term...", 20, 10, 150, 22)

Populate()
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            FileDelete($Fill)
            Exit
        Case $Button2
            Search()
    EndSwitch
WEnd


Func Populate()
    Local $aArray = IniReadSectionNames($Fill)
    If Not @error Then
        ; Enumerate through the array displaying the section names.
        For $i = 1 To $aArray[0]
        $Value = IniRead($Fill, $aArray[$i], "1", "")
        GUICtrlCreateListViewItem($aArray[$i] & "|" & $Value, $LV)
        ;_GUICtrlListView_SimpleSort($ListView1, $Sort, 0, False) ;<<<<<<<<<<<<<< Works but slows down load time.
        Next
    EndIf
EndFunc


Func Search()
    $value = GUICtrlRead($Input)
    $iI = _GUICtrlListView_FindInText($LV, $value, -1)
    _GUICtrlListView_EnsureVisible($LV, $iI)
EndFunc

Thanks for your help so far.

Dan

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Try this. The search is in the Item field. Press 1 to get all items with "1" in the item field.

#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>

Opt( "MustDeclareVars", 1 )

Global $hGui, $hEdit, $idEditSearch, $hLV, $iItems = 1000, $aItems[$iItems][2], $aSearch[$iItems], $iSearch = 0, $Fill

Example()


Func Example()
  $Fill = @ScriptDir & "\sample.ini"
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM1", "1=2")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM2", "1=3")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM3", "1=4")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM4", "1=5")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM5", "1=6")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM6", "1=7")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM7", "1=8")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM8", "1=9")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM9", "1=10")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM10", "1=11")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM11", "1=12")

  ; Create GUI
  $hGui = GUICreate( "Gui", 300, 230 )

  ; Create Edit control
  Local $idEdit = GUICtrlCreateEdit( "", 10, 10, 300-20, 20, BitXOR( $GUI_SS_DEFAULT_EDIT, $WS_HSCROLL, $WS_VSCROLL ) )
  $hEdit = GUICtrlGetHandle( $idEdit )
  $idEditSearch = GUICtrlCreateDummy()

  ; Handle $WM_COMMAND messages from Edit control
  ; To be able to read the search string dynamically while it's typed in
  GUIRegisterMsg( $WM_COMMAND, "WM_COMMAND" )

  ; Create ListView                                                Virtual listview
  Local $idLV = GUICtrlCreateListView( "", 10, 40, 300-20, 200-20, $LVS_OWNERDATA )
  $hLV = GUICtrlGetHandle( $idLV )
  _GUICtrlListView_SetExtendedListViewStyle( $hLV, BitOR( $LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES ) )
  _GUICtrlListView_AddColumn( $hLV, "Item",  130 )
  _GUICtrlListView_AddColumn( $hLV, "Value", 125 )

  ; Handle $WM_NOTIFY messages from ListView
  ; Necessary to display the rows in a virtual ListView
  GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )

  ; Show GUI
  GUISetState( @SW_SHOW )

  ; Fill array
  Local $aArray = IniReadSectionNames($Fill), $Value
  If Not @error Then
    ; Enumerate through the array displaying the section names.
    For $i = 1 To $aArray[0]
      $Value = IniRead($Fill, $aArray[$i], "1", "")
      $aItems[$i-1][0] = $aArray[$i]
      $aItems[$i-1][1] = $Value
    Next
    $iItems = $aArray[0]
  EndIf

  ; Set search array to include all items
  For $i = 0 To $iItems - 1
    $aSearch[$i] = $i
  Next
  $iSearch = $iItems

  ; Display items
  GUICtrlSendMsg( $idLV, $LVM_SETITEMCOUNT, $iSearch, 0 )

  ; Message loop
  While 1
    Switch GUIGetMsg()
      Case $idEditSearch
        Local $sSearch = GUICtrlRead( $idEdit )
        If $sSearch = "" Then
          ; Empty search string, display all rows
          For $i = 0 To $iItems - 1
            $aSearch[$i] = $i
          Next
          $iSearch = $iItems
        Else
          ; Find rows matching the search string
          $iSearch = 0
          For $i = 0 To $iItems - 1
            If StringInStr( $aItems[$i][0], $sSearch ) Then ; Normal search
            ;If StringRegExp( $aItems[$i][0], $sSearch ) Then ; Reg. exp. search
              $aSearch[$iSearch] = $i
              $iSearch += 1
            EndIf
          Next
        EndIf
        ; Display items
        GUICtrlSendMsg( $idLV, $LVM_SETITEMCOUNT, $iSearch, 0 )
        ConsoleWrite( StringFormat( "%4d", $iSearch ) & " rows matching """ & $sSearch & """" & @CRLF )

      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
  WEnd

  GUIDelete()
EndFunc

Func WM_COMMAND( $hWnd, $iMsg, $wParam, $lParam )
  Local $hWndFrom = $lParam
  Local $iCode = BitShift( $wParam, 16 ) ; High word
  Switch $hWndFrom
    Case $hEdit
      Switch $iCode
        Case $EN_CHANGE
          GUICtrlSendToDummy( $idEditSearch )
      EndSwitch
  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc

Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam )
  Local Static $tText = DllStructCreate( "wchar[50]" )
  Local Static $pText = DllStructGetPtr( $tText )

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

  Switch $hWndFrom
    Case $hLV
      Switch $iCode
        Case $LVN_GETDISPINFOW
          Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam )
          If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then
            Local $sItem = $aItems[$aSearch[DllStructGetData($tNMLVDISPINFO,"Item")]][DllStructGetData($tNMLVDISPINFO,"SubItem")]
            DllStructSetData( $tText, 1, $sItem )
            DllStructSetData( $tNMLVDISPINFO, "Text", $pText )
            DllStructSetData( $tNMLVDISPINFO, "TextMax", StringLen( $sItem ) )
          EndIf
      EndSwitch
  EndSwitch

  Return $GUI_RUNDEFMSG
EndFunc

 

Edited by LarsJ

Share this post


Link to post
Share on other sites

That works great Lars, I am working on implementing that into my code now. I have to say its some clever stuff! It seems this particular function is a lot harder to achieve that i first thought it would be. 

I started with 3 lines of code and almost had it doing what i wanted and now i have 144 lines :lmao:

Got to admit i still do not understand it but I am going to give it a shot!

Cheers

Dan

Share this post


Link to post
Share on other sites

Here is another example of filtering a LlistView.

#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>

Global $idListview, $iNoCols = 2, $iNoItems = 1000, $aArrData[$iNoItems][$iNoCols], $idInput

Example()

Func Example()
    Local $sCols = "col0"
    GUICreate("ListView Original", 500, 350, -1, -1, $WS_SIZEBOX)
    GUICtrlCreateLabel("Filter", 4, 302)
    GUICtrlSetResizing(-1, $GUI_DOCKBOTTOM + $GUI_DOCKHEIGHT + $GUI_DOCKLEFT + $GUI_DOCKWIDTH)
    $idInput = GUICtrlCreateInput("", 40, 302, 355, 25)
    GUICtrlSetResizing($idInput, $GUI_DOCKBOTTOM + $GUI_DOCKHEIGHT + $GUI_DOCKLEFT)

    For $m = 1 To $iNoCols - 1
        $sCols &= "|col" & $m
    Next
    $idListview = GUICtrlCreateListView($sCols, 0, 0, 500, 300)
    GUICtrlSetResizing($idListview, $GUI_DOCKBOTTOM + $GUI_DOCKTOP)

    ; ------- Create data in array for ListView ------------------
    $Fill = @ScriptDir & "\sample.ini"
    For $i = 1 To $iNoItems
        IniWrite(@ScriptDir & "\sample.ini", "ITEM", "ITEM " & $i, $i + 1)
    Next
    $aArrData = IniReadSection(@ScriptDir & "\sample.ini", "ITEM")
    _ArrayDelete($aArrData, 0) ; Remove number of elements from array

    _GUICtrlListView_AddArray($idListview, $aArrData)
    _GUICtrlListView_SetColumnWidth($idListview, 0, 80)

    GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND")
    GUISetState(@SW_SHOW)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd
    GUIDelete()
EndFunc   ;==>Example

Func MY_WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    Local $iIDFrom = BitAND($wParam, 0xFFFF);LoWord
    Local $iCode = BitShift($wParam, 16) ;HiWord
    If $iIDFrom = $idInput And $iCode = $EN_CHANGE Then
        _GUICtrlListView_DeleteAllItems($idListview)
        _GUICtrlListView_AddArray($idListview, $aArrData)
        $sFind = GUICtrlRead($idInput)
        If $sFind <> "" Then
            For $i = _GUICtrlListView_GetItemCount($idListview) To 0 Step -1
                $sText = _GUICtrlListView_GetItemText($idListview, $i)
                If StringInStr($sText, $sFind) = 0 Then _GUICtrlListView_DeleteItem($idListview, $i); <<<< Apply filter
            Next
        EndIf
    EndIf
EndFunc   ;==>MY_WM_COMMAND

 

Share this post


Link to post
Share on other sites

goss34, Yesterday you reported a problem about extracting data from a virtual listview on double click. It seems as if your thread got lost because of the failed upgrade of the forum software and the subsequent restore of the backup from friday morning.

In your thread from yesterday you were referring to an old case. I have found the old case and added the answer here.

You were using this code in the WM_NOTIFY function to extract data on double click:

Local $sSelected = _GUICtrlListView_GetItemTextString( $hLV, -1 )
ConsoleWrite( "Double Click" & @CR & $sSelected & @CR )

_GUICtrlListView_GetItemTextString does not work for a virtual listview. Instead, you need to extract data directly from the array that feeds your listview:

#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>

Opt( "MustDeclareVars", 1 )

Global $hGui, $hEdit, $idEditSearch, $hLV, $iItems = 1000, $aItems[$iItems][2], $aSearch[$iItems], $iSearch = 0, $Fill

Example()


Func Example()
  $Fill = @ScriptDir & "\sample.ini"
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM1", "1=2")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM2", "1=3")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM3", "1=4")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM4", "1=5")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM5", "1=6")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM6", "1=7")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM7", "1=8")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM8", "1=9")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM9", "1=10")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM10", "1=11")
  IniWriteSection(@ScriptDir & "\sample.ini", "ITEM11", "1=12")

  ; Create GUI
  $hGui = GUICreate( "Gui", 300, 230 )

  ; Create Edit control
  Local $idEdit = GUICtrlCreateEdit( "", 10, 10, 300-20, 20, BitXOR( $GUI_SS_DEFAULT_EDIT, $WS_HSCROLL, $WS_VSCROLL ) )
  $hEdit = GUICtrlGetHandle( $idEdit )
  $idEditSearch = GUICtrlCreateDummy()

  ; Handle $WM_COMMAND messages from Edit control
  ; To be able to read the search string dynamically while it's typed in
  GUIRegisterMsg( $WM_COMMAND, "WM_COMMAND" )

  ; Create ListView                                                Virtual listview
  Local $idLV = GUICtrlCreateListView( "", 10, 40, 300-20, 200-20, $LVS_OWNERDATA )
  $hLV = GUICtrlGetHandle( $idLV )
  _GUICtrlListView_SetExtendedListViewStyle( $hLV, BitOR( $LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES ) )
  _GUICtrlListView_AddColumn( $hLV, "Item",  130 )
  _GUICtrlListView_AddColumn( $hLV, "Value", 125 )

  ; Handle $WM_NOTIFY messages from ListView
  ; Necessary to display the rows in a virtual ListView
  GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )

  ; Show GUI
  GUISetState( @SW_SHOW )

  ; Fill array
  Local $aArray = IniReadSectionNames($Fill), $Value
  If Not @error Then
    ; Enumerate through the array displaying the section names.
    For $i = 1 To $aArray[0]
      $Value = IniRead($Fill, $aArray[$i], "1", "")
      $aItems[$i-1][0] = $aArray[$i]
      $aItems[$i-1][1] = $Value
    Next
    $iItems = $aArray[0]
  EndIf

  ; Set search array to include all items
  For $i = 0 To $iItems - 1
    $aSearch[$i] = $i
  Next
  $iSearch = $iItems

  ; Display items
  GUICtrlSendMsg( $idLV, $LVM_SETITEMCOUNT, $iSearch, 0 )

  ; Message loop
  While 1
    Switch GUIGetMsg()
      Case $idEditSearch
        Local $sSearch = GUICtrlRead( $idEdit )
        If $sSearch = "" Then
          ; Empty search string, display all rows
          For $i = 0 To $iItems - 1
            $aSearch[$i] = $i
          Next
          $iSearch = $iItems
        Else
          ; Find rows matching the search string
          $iSearch = 0
          For $i = 0 To $iItems - 1
            If StringInStr( $aItems[$i][0], $sSearch ) Then ; Normal search
            ;If StringRegExp( $aItems[$i][0], $sSearch ) Then ; Reg. exp. search
              $aSearch[$iSearch] = $i
              $iSearch += 1
            EndIf
          Next
        EndIf
        ; Display items
        GUICtrlSendMsg( $idLV, $LVM_SETITEMCOUNT, $iSearch, 0 )
        ConsoleWrite( StringFormat( "%4d", $iSearch ) & " rows matching """ & $sSearch & """" & @CRLF )

      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
  WEnd

  GUIDelete()
EndFunc

Func WM_COMMAND( $hWnd, $iMsg, $wParam, $lParam )
  Local $hWndFrom = $lParam
  Local $iCode = BitShift( $wParam, 16 ) ; High word
  Switch $hWndFrom
    Case $hEdit
      Switch $iCode
        Case $EN_CHANGE
          GUICtrlSendToDummy( $idEditSearch )
      EndSwitch
  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc

Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam )
  Local Static $tText = DllStructCreate( "wchar[50]" )
  Local Static $pText = DllStructGetPtr( $tText )

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

  Switch $hWndFrom
    Case $hLV
      Switch $iCode
        Case $LVN_GETDISPINFOW
          Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam )
          If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then
            Local $sItem = $aItems[$aSearch[DllStructGetData($tNMLVDISPINFO,"Item")]][DllStructGetData($tNMLVDISPINFO,"SubItem")]
            DllStructSetData( $tText, 1, $sItem )
            DllStructSetData( $tNMLVDISPINFO, "Text", $pText )
            DllStructSetData( $tNMLVDISPINFO, "TextMax", StringLen( $sItem ) )
          EndIf
        Case $NM_DBLCLK
          ;Local $sSelected = _GUICtrlListView_GetItemTextString( $hLV, -1 )
          Local $tNMITEMACTIVATE = DllStructCreate( $tagNMITEMACTIVATE, $lParam )
          Local $iIndex = DllStructGetData( $tNMITEMACTIVATE, "Index" )
          Local $sSelected = $aItems[$aSearch[$iIndex]][0] & "|" & _ ; Column 0
                             $aItems[$aSearch[$iIndex]][1]           ; Column 1
          ConsoleWrite( "Double Click" & @CR & $sSelected & @CR )
      EndSwitch
  EndSwitch

  Return $GUI_RUNDEFMSG
EndFunc

 

Share this post


Link to post
Share on other sites

Hi Lars,

Thank you so much for replying even though the new thread disappeared, much appreciated.

I have managed to implement the double click using the example above but i am struggling to come up with a way to launch a function after the doubleclick without hanging the listview, it still produces the blanked out row.

I have worked around it so it does what i want but it does hang the listview and i need to scroll after the function finishes in order to get it to redraw the entries. I am pretty sure i am missing something simple but could use a pointer :'(

Cheers

Dan

Share this post


Link to post
Share on other sites

Nevermind Lars,

Got there in the end, i knew why it was hanging but didnt know how to get what i wanted to action.

Re-read the tutorial - https://www.autoitscript.com/wiki/Tutorial_GUIRegisterMsg and a post of Melbas and sorted the code accordingly so i now set a value to true after the double click and process an action under the while so it no longer hangs the GUI.

Thanks for all your help as usual.

Dan

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

  • Similar Content

    • buymeapc
      By buymeapc
      Hi all,
      I'm trying to create a listview with subitem icons and I achieved this by simply rearranging the order of the columns, so that the first column is in the middle, thus appearing as a subitem with an icon - this method prevents the "icon clipping" that happens when using subitem icons in a listview. My issue is that when I select a row that does not have an icon, the space where the icon would be is white. Is there a way to make this transparent, so it looks like the entire row is selected?
      Here's an example - click the second listview item/row to see a blank space where the icon would be.
      #include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <WindowsConstants.au3> _Main() Func _Main() Local $hGui, $listview, $hImage Local $iLV_EXStyle_NoChecks = BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_DOUBLEBUFFER, $LVS_EX_HEADERDRAGDROP) $hGui = GUICreate("Listview Test With Icons", 400, 300) $listview = GUICtrlCreateListView("Col 1|Col 2|Col 3", 2, 2, 394, 268, BitOR($LVS_REPORT, $LVS_SHAREIMAGELISTS)) _GUICtrlListView_SetExtendedListViewStyle($listview, $iLV_EXStyle_NoChecks) GUISetState() ; Create the image list $hImage = _GUIImageList_Create(16, 16, 5, 3) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 165) _GUICtrlListView_SetImageList($listview, $hImage, 1) ; Set the order so the first column is moved to the middle, ; acting like a subitem with an icon _GUICtrlListView_SetColumnOrder($listview, "1|0|2") ; Add the items GUICtrlCreateListViewItem("Item1|Item2|Item3", $listview) GUICtrlCreateListViewItem("Item4|Item5|Item6", $listview) ; Set an icon for just the first item _GUICtrlListView_SetItemImage($listview, 0, 0) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() EndFunc ;==>_Main  
    • rkr
      By rkr
      Hi, i want to read a particular string from a text file using autoit. i wish to read it without explicitly opening the text file. the copied string should be then transferred to an excelbook (again, no need to explicitly open the excel book)... 

      with reference to my screenshot attached, my input to the  'script'' is going to be 0017-0008, and the script should copy the highlighted two lines from the input file to excel
      thanks

    • Luigi
      By Luigi
      Greetings forum,
      Hi develop this script, to use context menu with listview.
      It's work fine, run and click with left or right mouse button, you see on Console the id from item.
      If you click none, the id is -1, like this:
      $NM_RCLICK[-1] $NM_RCLICK[-1] $NM_RCLICK[2] $NM_RCLICK[1] $NM_RCLICK[0] $NM_RCLICK[1] That is correct.
      But if you uncoment the line:
      GUIRegisterMsg($WM_CONTEXTMENU, "WM_CONTEXTMENU")
      You have to click with left button (over item or none) and after click with right button.
      LeftButton is to update $HOSTS_INDEX.
      RightButton is to open ContextMenu.
       
      Exist another way to update $HOSTS_INDEX?
      Example:
      Call WM_NOTIFY every time WM_CONTEXTMENU is called?
      I ask this, becouse i cant understanding why $HOSTS_INDEX is not updated when WM_CONTEXTMENU is uncomented.
      Someone can explain or help me?
       
      Best regards.
      ;~ #AutoIt3Wrapper_AU3Check_Parameters= -q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7 ;~ #Tidy_Parameters=/sf #include-once #include-once #include <Array.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <GuiMenu.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> #include <SendMessage.au3> #include <Timers.au3> #include <AutoItConstants.au3> #include <EditConstants.au3> #include <File.au3> #include <FontConstants.au3> #include <GuiComboBoxEx.au3> #include <GuiImageList.au3> #include <GuiTreeView.au3> #include <ListViewConstants.au3> #include <StaticConstants.au3> #include <TreeViewConstants.au3> #include <String.au3> OnAutoItExitRegister("OnExit") Opt("GUIOnEventMode", 1) Opt("GUIEventOptions", 1) Opt("MustDeclareVars", 1) Global Enum $eCREATE = 1000, $eUPDATE, $eDELETE, $eICON_TABLE, $eDEFAULT, $eEXPORT_HTML Global Const $EMPTY = -1 Global $HOSTS_INDEX = -1 Global $HOST_Host Global $aGuiSize[2] = [800, 600] Global $sGuiTitle = "GuiTitle" Global $hGui Global $iList, $hList $hGui = GUICreate($sGuiTitle, $aGuiSize[0], $aGuiSize[1]) GUISetOnEvent($GUI_EVENT_CLOSE, "Quit") $iList = GUICtrlCreateListView("nome", 20, 50, 240, 490) $hList = GUICtrlGetHandle($iList) _GUICtrlListView_SetColumnWidth($hList, 0, 236) Populate() GUISetState(@SW_SHOW, $hGui) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ;~ GUIRegisterMsg($WM_CONTEXTMENU, "WM_CONTEXTMENU") While Sleep(25) WEnd Func OnExit() GUISetState($hGui, @SW_HIDE) GUIDelete($hGui) EndFunc ;==>OnExit Func Quit() Exit EndFunc ;==>Quit Func Populate() Local $arr[4] = [3, "nome 1", "nome 2", "nome 3"] _GUICtrlListView_BeginUpdate($hList) _GUICtrlListView_DeleteAllItems($hList) For $ii = 1 To $arr[0] _GUICtrlListView_AddItem($hList, $arr[$ii]) Next _GUICtrlListView_SetItemSelected($hList, 0, True, True) _GUICtrlListView_EndUpdate($hList) EndFunc ;==>Populate Func WM_CONTEXTMENU($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam ConsoleWrite("WM_CONTEXTMENU..( $hWnd=" & $hWnd & ", $iMsg=" & $iMsg & ", $wParam=" & $wParam & ", $lParam=" & $lParam & " )" & @LF) Local $exec = 0 Local $hMenu Switch $wParam Case $hList Local $TRY_ID = _GUICtrlListView_GetHotItem($hList) If Not ($TRY_ID = $HOSTS_INDEX) Then $HOSTS_INDEX = $TRY_ID Local $aOrigin = _GUICtrlListView_GetOrigin($hList) ConsoleWrite("WM_CONTEXTMENU $HOSTS_INDEX[" & $HOSTS_INDEX & "] $aOrigin[" & _GUICtrlListView_GetOriginX($iList) & "]" & @LF) $hMenu = _GUICtrlMenu_CreatePopup() If $HOSTS_INDEX = $EMPTY Then _GUICtrlMenu_InsertMenuItem($hMenu, 0, "Add", $eCREATE) Else _GUICtrlMenu_InsertMenuItem($hMenu, 0, "Rename", $eUPDATE) _GUICtrlMenu_InsertMenuItem($hMenu, 1, "Del", $eDELETE) EndIf _GUICtrlMenu_SetMenu($hGui, $hMenu) $exec = _GUICtrlMenu_TrackPopupMenu($hMenu, $wParam, -1, -1, 1, 1, 2, 1) _GUICtrlMenu_DestroyMenu($hMenu) EndSwitch Return True EndFunc ;==>WM_CONTEXTMENU Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Local $TRY_ID Switch $hWndFrom Case $hList $TRY_ID = _GUICtrlListView_GetHotItem($hList) If Not ($TRY_ID = $HOSTS_INDEX) Then $HOSTS_INDEX = $TRY_ID Switch $iCode Case $NM_CLICK ConsoleWrite("$NM_CLICK[" & $TRY_ID & "]" & @LF) If $HOSTS_INDEX = $EMPTY Or $HOST_Host Then ;~ HOSTS_Clear() ;~ HOSTS_ListView_ItemCancel() ;~ GUICtrlSetState($HOSTS_ITEM_DEL, $GUI_DISABLE) ;~ GUICtrlSetState($HOSTS_ITEM_UPD, $GUI_DISABLE) Else Local $name = _GUICtrlListView_GetItemText($hList, $HOSTS_INDEX) ;~ HOSTS_FieldLoad($name) ;~ GUICtrlSetState($HOSTS_ITEM_DEL, $GUI_ENABLE) ;~ GUICtrlSetState($HOSTS_ITEM_UPD, $GUI_ENABLE) EndIf Return 0 ; allow the default processing Case $NM_RCLICK ConsoleWrite("$NM_RCLICK[" & $TRY_ID & "]" & @LF) Return 0 ; allow the default processing EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY  
    • amphoric
      By amphoric
      Hi,
      I am struggling converting my 1D array to a 2D array and then showing that in my List View. Below is my current code, where I would like to take the array from the input box, and have that displayed as a list within the list view this is a list of computer names, and then update the 2nd column of each line once I have ran a ping and a registry change on each computer name, with either 'Completed' and 'Failed'
      I have checked out the AutoIt Arrays page here: https://www.autoitscript.com/wiki/Arrays , but unfortunately I cannot get my head around it. Any help would be greatly appreciated.
      I hope this makes sense.
      Thanks
       
      #include <Date.au3> #include <ButtonConstants.au3> #include <ComboConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <Array.au3> #include <MsgBoxConstants.au3> #include <GUIListBox.au3> #include <GuiListView.au3> #Region ### $Form1 = GUICreate("Title", 515, 533, -1, -1) GUISetBkColor(0xFFFFFF) $Pic2 = GUICtrlCreatePic("Images\pic.jpg", 16, 16, 212, 28) $Label1 = GUICtrlCreateLabel("Label", 240, 16, 271, 33, $SS_CENTER) GUICtrlSetFont(-1, 17, 800, 0, "") $Combo1 = GUICtrlCreateCombo("", 256, 406, 241, 25, BitOR($GUI_SS_DEFAULT_COMBO,$CBS_SIMPLE)) $Label2 = GUICtrlCreateLabel("Please select the location", 45, 401, 210, 20, $SS_CENTER) GUICtrlSetFont(-1, 10, 800, 0, "") $ChangeButton = GUICtrlCreateButton("Change", 286, 487, 75, 25) $RePromptButton = GUICtrlCreateButton("Re-prompt User", 366, 487, 139, 25) $Checkbox1 = GUICtrlCreateCheckbox("I have ensured that my selection is correct.", 10, 487, 273, 25) GUICtrlSetFont(-1, 10, 400, 0, "") $ManLocation = GUICtrlCreateLabel("Please enter the location:", 59, 448, 189, 20, $SS_RIGHT) GUICtrlSetFont(-1, 10, 800, 0, "") GUICtrlSetState(-1, $GUI_HIDE) $ManLocInput = GUICtrlCreateInput("", 256, 445, 241, 24) GUICtrlSetState(-1, $GUI_HIDE) $Label5 = GUICtrlCreateLabel("for this device:", 138, 418, 109, 20, $SS_CENTER) GUICtrlSetFont(-1, 10, 800, 0, "") $Label3 = GUICtrlCreateLabel("Asset Number:", 98, 72, 107, 20, $SS_CENTER) GUICtrlSetFont(-1, 10, 800, 0, "") $Input1 = GUICtrlCreateInput("", 215, 69, 241, 24) $AddMulti = GUICtrlCreateLabel("Add Multiple Assets", 356, 55, 98, 13, $SS_RIGHT) GUICtrlSetFont(-1, 8, 400, 6, "") GUICtrlSetColor(-1, 0x808080) GUICtrlSetCursor (-1, 0) $List1 = GUICtrlCreateListView("", 16, 104, 481, 278) $Add = GUICtrlCreateButton("Add", 461, 68, 35, 25) GUISetState(@SW_SHOW) #EndRegion ### ;### StartForm ### $FormaMultiple = GUICreate("Title", 277, 418, -1, -1) GUISetBkColor(0xFFFFFF) $Label1 = GUICtrlCreateLabel("Please add 1 asset number per line.", 8, 11, 253, 20, $SS_CENTER) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") $OK = GUICtrlCreateButton("OK", 56, 375, 75, 25) $Edit1 = GUICtrlCreateEdit("", 20, 40, 233, 329) $Cancel = GUICtrlCreateButton("Cancel", 136, 375, 75, 25) GUISetState(@SW_HIDE) ;### EndForm ### ;### Add List View Columns START ### ;### Add List View Columns END ### ;### Read Locations START ### ;Read the LOCAL ini file SECTIONS Global $aSections = IniReadSectionNames("Locations.ini") ;If the above succeeded, convert the array to a string with each item separated by a | (pipe) and set the default selected item to $aSections[1] If(Not @Error) Then GUICtrlSetData($Combo1, _ArraytoString($aSections, "|", 1), $aSections[1]) ;### Read Locations END ### ;### Require Admin START ### ;#RequireAdmin ;### Require Admin END ### While 1 $nMsg = GUIGetMsg() ;### Data Validation START ### ;Set Checkbox = ENABLE/DISABLE if not GUICtrlRead($Combo1) = "" AND GUICtrlRead($Combo1) = "Not In List" then if not GUICtrlRead($ManLocInput) = "" Then If not ControlCommand($Form1, "", $Checkbox1, "IsEnabled") Then GUICtrlSetState($Checkbox1, $GUI_ENABLE) Else If ControlCommand($Form1, "", $Checkbox1, "IsEnabled") Then GUICtrlSetState($Checkbox1, $GUI_DISABLE) EndIf Else if GUICtrlRead($Combo1) = "" Then If ControlCommand($Form1, "", $Checkbox1, "IsEnabled") Then GUICtrlSetState($Checkbox1, $GUI_DISABLE) Else If not ControlCommand($Form1, "", $Checkbox1, "IsEnabled") Then GUICtrlSetState($Checkbox1, $GUI_ENABLE) EndIf EndIf ;Set Button = ENABLE/DISABLE If GUICtrlRead($Checkbox1) = 1 Then If Not ControlCommand($Form1, "", $ChangeButton, "IsEnabled") Then GUICtrlSetState($ChangeButton, $GUI_ENABLE) Else If ControlCommand($Form1, "", $ChangeButton, "IsEnabled") Then GUICtrlSetState($ChangeButton, $GUI_DISABLE) EndIf ;### Data Validation END ### Switch $nMsg Case $GUI_EVENT_CLOSE Exit case $Add Case $AddMulti GUISetState(@SW_SHOW, $FormaMultiple) Case $Cancel GUISetState(@SW_HIDE, $FormaMultiple) Case $OK $sText = GUICtrlRead($Edit1) $aText = StringSplit($sText, @CRLF, 1) $bText = _ArrayToString($aText, ";", 1, -1) $cText = StringStripWS($bText, $STR_STRIPALL ) $dText = StringReplace($cText,";;",";") GUICtrlSetData($Input1, $dText) GUICtrlSetData($Edit1, "") GUISetState(@SW_HIDE, $FormaMultiple) For $i = 1 To $aText[0] Next Case $Combo1 ; If the combo is actioned Switch GUICtrlRead($Combo1) Case "Not In List" ; Show the manual input controls GUICtrlSetState($ManLocation, $GUI_SHOW) GUICtrlSetState($ManLocInput, $GUI_SHOW) if ControlCommand($Form1, "", $Checkbox1, "IsChecked") then ControlCommand($Form1, "", $Checkbox1, "Uncheck") GUICtrlSetData($ManLocInput, "") Case Else ; Hide them GUICtrlSetState($ManLocation, $GUI_HIDE) GUICtrlSetState($ManLocInput, $GUI_HIDE) if ControlCommand($Form1, "", $Checkbox1, "IsChecked") then ControlCommand($Form1, "", $Checkbox1, "Uncheck") GUICtrlSetData($ManLocInput, "") EndSwitch Case $ChangeButton ChangeReg() Case $RePromptButton RemoveReg() EndSwitch WEnd Func ChangeReg() $MultiAssets = StringSplit(GUICtrlRead($Input1), ";", 1) For $i = 1 To $MultiAssets[0] ; Ping with a timeout of 250ms. Local $iPing = Ping($MultiAssets[$i], 250) If $iPing Then ; If a value greater than 0 was returned then do the following: if not GUICtrlRead($ManLocInput) = "" Then RegWrite("\\" & $MultiAssets[$i] & "\HKLM\SOFTWARE\Location", "Location", "REG_SZ", "# - " & GUICtrlRead($ManLocInput)) RegWrite("\\" & $MultiAssets[$i] & "\HKLM64\SOFTWARE\Location", "Location", "REG_SZ", "# - " & GUICtrlRead($ManLocInput)) RegWrite("\\" & $MultiAssets[$i] & "\HKLM\SOFTWARE\Location", "LocationLog", "REG_SZ", @MDAY & "/" & @MON & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC) RegWrite("\\" & $MultiAssets[$i] & "\HKLM64\SOFTWARE\Location", "LocationLog", "REG_SZ", @MDAY & "/" & @MON & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC) MsgBox($MB_SYSTEMMODAL, "Completed", "Completed") Else If not GUICtrlRead($Input1) = "" Then RegWrite("\\" & $MultiAssets[$i] & "\HKLM\SOFTWARE\Location", "Location", "REG_SZ", GUICtrlRead($Combo1)) RegWrite("\\" & $MultiAssets[$i] & "\HKLM64\SOFTWARE\Location", "Location", "REG_SZ", GUICtrlRead($Combo1)) RegWrite("\\" & $MultiAssets[$i] & "\HKLM\SOFTWARE\Location", "LocationLog", "REG_SZ", @MDAY & "/" & @MON & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC) RegWrite("\\" & $MultiAssets[$i] & "\HKLM64\SOFTWARE\Location", "LocationLog", "REG_SZ", @MDAY & "/" & @MON & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC) MsgBox($MB_SYSTEMMODAL, "Completed", $MultiAssets[$i] & @CRLF & " Changed to: " & GUICtrlRead($Combo1)) Else MsgBox($MB_SYSTEMMODAL, "Error", "Please ensure all boxes are completed") EndIf EndIf Else MsgBox($MB_SYSTEMMODAL, "Error", "This asset may be OFFLINE, unable to complete") EndIf Next EndFunc ;==>PingReg Func RemoveReg() $MultiAssets = StringSplit(GUICtrlRead($Input1), ";", 1) For $i = 1 To $MultiAssets[0] ; Ping with a timeout of 250ms. Local $iPing = Ping($MultiAssets[$i], 250) If $iPing Then ; If a value greater than 0 was returned then do the following: if not GUICtrlRead($ManLocInput) = "" Then RegWrite("\\" & $MultiAssets[$i] & "\HKLM\SOFTWARE\Location", "Location", "REG_SZ", "") RegWrite("\\" & $MultiAssets[$i] & "\HKLM64\SOFTWARE\Location", "Location", "REG_SZ", "") RegWrite("\\" & $MultiAssets[$i] & "\HKLM\SOFTWARE\Location", "LocationLog", "REG_SZ", "") RegWrite("\\" & $MultiAssets[$i] & "\HKLM64\SOFTWARE\Location", "LocationLog", "REG_SZ", "") MsgBox($MB_SYSTEMMODAL, "Completed", "Completed") Else If not GUICtrlRead($Input1) = "" Then RegWrite("\\" & $MultiAssets[$i] & "\HKLM\SOFTWARE\Location", "Location", "REG_SZ", "") RegWrite("\\" & $MultiAssets[$i] & "\HKLM64\SOFTWARE\Location", "Location", "REG_SZ", "") RegWrite("\\" & $MultiAssets[$i] & "\HKLM\SOFTWARE\Location", "LocationLog", "REG_SZ", "") RegWrite("\\" & $MultiAssets[$i] & "\HKLM64\SOFTWARE\Location", "LocationLog", "REG_SZ", "") MsgBox($MB_SYSTEMMODAL, "Completed", $MultiAssets[$i] & @CRLF & "CLEARED") Else MsgBox($MB_SYSTEMMODAL, "Error", "Please ensure all boxes are completed") EndIf EndIf Else MsgBox($MB_SYSTEMMODAL, "Error", "This asset may be OFFLINE, unable to complete") EndIf Next EndFunc ;==>PingReg1  
    • Monica
      By Monica
      Hi guys!! I'm going crazy... please help me -.-
      First, open the attached screenshot. Second: I'd like to grab info from external window. The program is "Metatrader4", a tool for trading and charts analysis.
      The function _GUICtrlListView_GetItemText() return an empty string! I tried to change the index $index (the second parameter) into Number($index), as recommended by other similar posts in this forum, but this did not solve my problem 
      Well, why I'm going mad? Because in my mind an UDF approach works great or it does not work at all; instead, in my code something works and something else does not. I really don't understand why... and you?
      THXX!!!!  
      $handle=ControlGetHandle("Expert - "&$expertname,"",1383);List: Variable|Value For $i=0 To _GUICtrlListView_GetItemCount($handle)-1;WORKS!!! $temp=_GUICtrlListView_GetItemText($handle,0+$i);RETURN EMPTY STRING :-( MsgBox(0, "", $temp) $temp = _GUICtrlListView_GetItemSelected($handle,$i);WORKS!!! MsgBox(0, "", $temp) Next