Jump to content
goss34

Search In ListView (Redraw with matching string)

Recommended Posts

goss34

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
Malkey

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
LarsJ

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
goss34

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
goss34

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
LarsJ

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
goss34

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
Malkey

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
LarsJ

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
goss34

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
goss34

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

    • mistersquirrle
      By mistersquirrle
      Hello!
       
      I wrote myself a script to follow Google Maps Polyline encoding steps: https://developers.google.com/maps/documentation/utilities/polylinealgorithm, and that works (although I think that it's a bit janky), but now I'm having issues getting the output.
       
      When I run the script, all the points come out correctly in the console, and even when they're the only things that I log, it displays them fine. However, I'm adding each point into a variable to return all of them at once at the end, fully formatted, and it's only taking the very first point. I can't figure out what I'm doing wrong, as it seems fine.
       
      When run with the default value, it should output this at the end: Custom Polygon: _p~iF~ps|U_ulLnnqC_mqNvxq`@
      But instead I'm just getting this: Custom Polygon: _p~iF
       
      I know that it's reaching the string combination lines because it's logging the data before it (and even if a put log AFTER the $sPolygon &= $aPoints[0], it's logged fine).
       
      Here's my full code (problem is lines ~209 - 234, search "$sPolygon &= $aPoints[1]"):
      #include <Array.au3> #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> _PolyGUI() Func _PolyGUI() #Region ### START Koda GUI section ### Form= $hInputGUI = GUICreate("Lat Long encoder", 403, 301, 192, 124) GUISetFont(8, 400, 0, "Consolas") GUICtrlCreateLabel("Input polygon points here, format as:", 8, 8, 263, 19) GUICtrlSetFont(-1, 10, 800, 0, "Consolas") GUICtrlCreateLabel("Lat Long - Single point", 8, 24, 142, 17) GUICtrlCreateLabel("Lat Long, Lat Long, Lat Long - Multiple points", 8, 40, 280, 17) Local $sPoints = GUICtrlCreateEdit("", 8, 64, 385, 201, BitOR($ES_WANTRETURN, $WS_VSCROLL)) GUICtrlSetData(-1, "38.5 -120.2, 40.7 -120.95, 43.252 -126.453") GUICtrlSetFont(-1, 10, 400, 0, "Consolas") $bOK = GUICtrlCreateButton("bOK", 16, 272, 123, 25) GUICtrlSetFont(-1, 12, 800, 0, "Consolas") $bCancel = GUICtrlCreateButton("bCancel", 304, 272, 75, 25) GUICtrlSetFont(-1, 12, 800, 0, "Consolas") GUISetState(@SW_SHOW, $hInputGUI) #EndRegion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $bCancel Exit Case $bOK $sPoints = GUICtrlRead($sPoints) GUISetState(@SW_HIDE, $hInputGUI) _GetPoly($sPoints, True) ExitLoop EndSwitch Sleep(10) WEnd EndFunc ;==>_PolyGUI ;https://developers.google.com/maps/documentation/utilities/polylinealgorithm ;https://app.dsmobileidx.com/api/DescribeSearchForLinkId?linkId=469787 ; Note that this will only really work inside the US (this side of the World), as it's assuming any negative is the Longitude ;https://gist.github.com/ismaels/6636986 - decoder ;Using: 41.83162 -87.64696 ; Expected: sfi~F np}uO ; Actual: sfi~f np}uo ; If we remove 32 from the last ASCII code, since the last bit chunk is 0, we get the correct case/ characters ; We need to run this logic back through all the indexes though and do this to all that that <= 63 ;LinkId=469787 ; Expected: q{`aHpa_iVi[kp@}`Aa{@e[eCoqBbAyc@iRy{@g_@mz@|gA{eAh~@Vf~Etv@gB~p@gQ`^yg@~p@ekAldA{KfFxIrJ^pO~Mtl@dPrJnUz[nSpo@wf@fc@yw@n@ob@ ; Actual: s{`aHpa_iVg[kp@}`Aa{@g[gCmqBbA{c@iRy{@e_@kz@|gA{eAh~@Td~Evv@gB|p@gQb^wg@|p@ekAndA{KfFvIpJ`@rO~Mrl@dPrJnU|[lSpo@wf@dc@yw@n@mb@ ; I assume that this is because of bad data, the points have repeating 9's and 0's, which looks fishy. The polygon is (very) close, but not quite the same. Func _GetPoly($sPoints, $bLog = False) Local $timer = TimerInit(), $sConsole[11] Local $sPolygon = "" ; Step 1, take the initial signed value: Local $aCoords = StringRegExp($sPoints, "(-*?\d*\.\d*) (-*?\d*\.\d*)", 3), $aPoints[2] ;~ _ArrayDisplay($aCoords) If $bLog Then _Log(_ArrayToString($aCoords)) For $c = 0 To (UBound($aCoords) - 1) Step 2 ;~ If $bLog Then _Log($c) If $c = 0 Then $aPoints[0] = $aCoords[$c] $aPoints[1] = $aCoords[$c + 1] Else $aPoints[0] = $aCoords[$c] - $aCoords[$c - 2] $aPoints[1] = $aCoords[$c + 1] - $aCoords[$c - 1] EndIf If $bLog Then _Log("- Step 1, take the initial signed value:") _Log(" " & $aPoints[0]) _Log(" " & $aPoints[1]) EndIf ; Step 2, multiply each by 1e5, and round $aPoints[0] = Round($aPoints[0] * 1e5, 0) $aPoints[1] = Round($aPoints[1] * 1e5, 0) If $bLog Then _Log("- Step 2, multiply each by 1e5, and round") _Log(" " & $aPoints[0]) _Log(" " & $aPoints[1]) EndIf ; Step 3, convert Decimal to Binary, using two's complement for negatives. Padded to 32 bits $aPoints[0] = _NumberToBinary($aPoints[0]) $aPoints[1] = _NumberToBinary($aPoints[1]) If $bLog Then _Log("- Step 3, convert Decimal to Binary, using two's complement for negatives. Padded to 32 bits") _Log(" " & $aPoints[0]) _Log(" " & $aPoints[1]) EndIf ; Step 4, left-shifted 1 bit $aPoints[0] = StringTrimLeft($aPoints[0], 1) & "0" $aPoints[1] = StringTrimLeft($aPoints[1], 1) & "0" If $bLog Then _Log("- Step 4, left-shifted 1 bit") _Log(" " & $aPoints[0]) _Log(" " & $aPoints[1]) EndIf ; Step 5, if negative, invert binary If $c = 0 Then If $aCoords[$c] < 0 Then $aPoints[0] = _InvertBinary($aPoints[0]) If $aCoords[$c + 1] < 0 Then $aPoints[1] = _InvertBinary($aPoints[1]) Else If $aCoords[$c] - $aCoords[$c - 2] < 0 Then $aPoints[0] = _InvertBinary($aPoints[0]) If $aCoords[$c + 1] - $aCoords[$c - 1] < 0 Then $aPoints[1] = _InvertBinary($aPoints[1]) EndIf If $bLog Then _Log("- Step 5, if negative, invert binary") _Log(" " & $aPoints[0]) _Log(" " & $aPoints[1]) EndIf Local $aChunks[2][6], $0x20 For $i = 0 To 1 $0x20 = "1" ; This is out BitOR flag, 0x20 BitOR'd onto our 5-bit chunks is always 1*****, except the last chunk $sConsole[5] = "" ; Clearing console variables $sConsole[6] = "" $sConsole[7] = "" $sConsole[8] = "" $sConsole[9] = "" For $j = 0 To 5 ;There will always be 6 chunks ; Step 6 & 7, break into 5-bit chunks, and reverse order $aChunks[$i][$j] = StringTrimLeft($aPoints[$i], StringLen($aPoints[$i]) - 5) ; This splits into 5-bit chunks in reverse order, doing 6 & 7 in one operation ;~ If $bLog Then _Log(" " & $aPoints[$i]) ;~ If $bLog Then _Log(" " & StringLen($aPoints[$i])) ;~ If $bLog Then _Log(" " & StringTrimLeft($aPoints[$i], StringLen($aPoints[$i]) - 5)) ;~ If $bLog Then _Log(" " & $aChunks[$i][$j]) ; Here we consume the original binary string, so the next loop gets the correct next 5-bit chunk $aPoints[$i] = StringTrimRight($aPoints[$i], 5) $sConsole[5] &= $aChunks[$i][$j] & " " ; Once consumed, if the remaining length isn't enough for another bit chunk, switch 0x20 to 0 (no following chunks) If StringLen($aPoints[$i]) <= 5 Then $0x20 = "0" ; Step 8, BitOR 100000 (0x20) to our 5-bit chunks (effectively) $aChunks[$i][$j] = $0x20 & $aChunks[$i][$j] $sConsole[7] &= $aChunks[$i][$j] & " " ; Step 9, converting the chunk from Binary back to Decimal $aChunks[$i][$j] = _BinaryToDec($aChunks[$i][$j]) $sConsole[8] &= $aChunks[$i][$j] & " " ; Step 10, adding 63 to decimal values $aChunks[$i][$j] += 63 $sConsole[9] &= $aChunks[$i][$j] & " " If StringLen($aPoints[$i]) < 5 Then ExitLoop Next If $bLog Then _Log("- Step 6 & 7 (part " & $i & "), break into 5-bit chunks, and reverse order") _Log(" " & $sConsole[5]) _Log("- Step 8 (part " & $i & "), BitOR 100000 (0x20) to our 5-bit chunks (effectively)") _Log(" " & $sConsole[7]) _Log("- Step 9 (part " & $i & "), converting the chunk from Binary back to Decimal") _Log(" " & $sConsole[8]) _Log("- Step 10 (part " & $i & "), adding 63 to decimal values") _Log(" " & $sConsole[9]) EndIf Next Local $aASCII[0] For $i = 0 To 1 Dim $aASCII[0] ; Reset ASCII array For $j = 0 To (UBound($aChunks, 2) - 1) ; For both chunk sets ReDim $aASCII[UBound($aASCII) + 1] ; Add an index for the ASCII array If $aChunks[$i][$j] = "" Or $aChunks[$i][$j] <= 63 Then ; If the chunk is not useful $l = $j For $k = $l To 1 Step -1 If $aChunks[$i][$k] = "" Or $aChunks[$i][$k] <= 63 Or $aASCII[$k] <= 63 Then $aASCII[$k - 1] -= 32 If $aASCII[$k - 1] <= 63 Then _ArrayDelete($aASCII, $k - 1) Else ExitLoop EndIf Next ExitLoop EndIf $aASCII[$j] = Int($aChunks[$i][$j]) Next ;Step 11, convert each value to ASCII equivalent For $k = UBound($aASCII) - 1 To 0 If $aASCII[$k] <= 63 Or $aASCII[$k] = "" Then ReDim $aASCII[UBound($aASCII) - 1] Else ExitLoop EndIf Next $aPoints[$i] = StringFromASCIIArray($aASCII, 0, -1, 0) Next If $bLog Then _Log("- Step 11, convert each value to ASCII equivalent, finished") If $aCoords[$c] <= 0 Then ;@CRLF & " " & If $bLog Then _Log($aPoints[1]) _Log($aPoints[0]) _Log("Next set") EndIf $sPolygon &= $aPoints[1] $sPolygon &= $aPoints[0] Else If $bLog Then _Log($aPoints[0]) _Log($aPoints[1]) _Log("Next set") EndIf $sPolygon &= $aPoints[0] $sPolygon &= $aPoints[1] EndIf Next If $bLog Then _Log("Custom Polygon: " & $sPolygon) _Log(TimerDiff($timer) & @CRLF) EndIf Return $sPolygon EndFunc ;==>_GetPoly Func _NumberToBinary($iNumber) Local $sBinString = "" ; Maximum 32-bit # range is -2147483648 to 2147483647 If $iNumber < -2147483648 Or $iNumber > 2147483647 Then Return SetError(1, 0, "") ; Convert to a 32-bit unsigned integer. We can't work on signed #'s $iUnsignedNumber = BitAND($iNumber, 0x7FFFFFFF) ; Cycle through each bit, shifting to the right until 0 Do $sBinString = BitAND($iUnsignedNumber, 1) & $sBinString $iUnsignedNumber = BitShift($iUnsignedNumber, 1) Until Not $iUnsignedNumber ; Was it a negative #? Put the sign bit on top, and pad the bits that aren't set If $iNumber < 0 Then Return '1' & StringRight("000000000000000000000000000000" & $sBinString, 31) ; Always return 32 bit binaries If StringLen($sBinString) < 32 Then Return StringRight("0000000000000000000000000000000" & $sBinString, 32) Return $sBinString EndFunc ;==>_NumberToBinary Func _BinaryToDec($sBinary) Local Const $aPower[8] = [128, 64, 32, 16, 8, 4, 2, 1] Local $iDec If StringRegExp($sBinary, "[0-1]") Then If StringLen($sBinary) < 8 Then Do $sBinary = "0" & $sBinary Until StringLen($sBinary) = 8 EndIf $aBinary = StringSplit($sBinary, "", 2) For $i = 0 To UBound($aBinary) - 1 ;~ $aBinary[$i] = $aBinary[$i] * $aPower[$i] $iDec += $aBinary[$i] * $aPower[$i] Next Return $iDec Else Return SetError(0, 0, "Not a binary string") EndIf EndFunc ;==>_BinaryToDec Func _InvertBinary($iNumber) ;~ ConsoleWrite(@CRLF & $iNumber) Local $sNumber $aNumber = StringSplit($iNumber, "") For $i = 1 To $aNumber[0] If $aNumber[$i] = 0 Then $aNumber[$i] = 1 ElseIf $aNumber[$i] = 1 Then $aNumber[$i] = 0 Else Return SetError(0, 0, "Not a binary number") EndIf $sNumber &= String($aNumber[$i]) Next Return $sNumber EndFunc ;==>_InvertBinary Func _Log($data) ;~ Local Static $LogEnable = True ConsoleWrite(@CRLF & @HOUR & ":" & @MIN & "." & @SEC & " " & $data) LogData(@HOUR & ":" & @MIN & "." & @SEC & " " & $data, "logs/LOGFILE.txt") EndFunc ;==>_Log Func LogData($text, $File = "logs/LOGFILE.txt") Global $LogFile = "" If $LogFile = "" Then $LogFile = FileOpen($File, 9) OnAutoItExitRegister(CloseLog) EndIf FileWriteLine($LogFile, $text) EndFunc ;==>LogData Func CloseLog() If $LogFile <> "" Then _Log("Closing LoD script" & @CRLF) FileClose($LogFile) EndIf EndFunc ;==>CloseLog  
      I've tried:
      $sPolygon &= $aPoints[0] & $aPoints[1] ;---- $sPolygon = $sPolygon & $aPoints[0] & $aPoints[1] ;---- $sPolygon = $sPolygon & String($aPoints[0] & $aPoints[1]) ;---- $sPolygon = String($sPolygon) & String($aPoints[0]) & String($aPoints[1]) ;---- $sPolygon &= $aPoints[1] $sPolygon &= $aPoints[0] ;----  
      I'm sure it's something basic that I'm overlooking, but I don't understand why it's not combining the strings. 
      Also, unrelated, why doesn't $LogFile = FileOpen($File, 9) create the directory/ file if they don't exist? 9 should be $FO_CREATEPATH (8) + $FO_APPEND (1)?
      Thanks!
    • careca
      By careca
      This is another take on string triggers, triggers on specific strings.
      Able to simple text pasting,
      opening links (as long as there's a www. http:\\ or https:\\ at the beggining)
      and is able to open applications.
      The user selects the modifier key, and then uses a combination of that key with a couple others to perform tasks like
      screenshot the active window, (modkey + prtscr), turn off the screen (modkey + pause / break),
      open clipboard string in registry (modkey + R), change system volume (modkey + arrouw up/dn).
      The following keys pressed at the same time prompt for shutdown: S+D+T
      The following keys pressed at the same time prompt for restart: S+R+T
      Middle mouse button click on titlebar minimizes to tray, or a left mouse button click in the icon in the tray also minimizes.
      Trigger is set off by space or enter, and timeouts after 3 seconds.
      Shows your external, lan, and gateway ip's, can refresh with right mouse click, and opens the default browser if the correspondent button is pressed.
      Able to change system volume by a set percentage, reading from the inputbox the number the user sets, if 0 or empty uses system default.
      I made this because the existing string trigger applications didn't do it for me for a number of reasons.
      I did this for me, but if someone finds it useful all the better.
    • WoodGrain
      By WoodGrain
      Hi All,
      I'd like to replace 'COMMA' with ',' for example:
      $myString = "COMMA" StringRegExpReplace($myString, 'COMMA', ',') Now I've tried escaping the ',' in various ways unsuccessfully, such as:
      '[,]'
      "[,]"
      '\,'
      [,] seems to work in the pattern, I just can't figure out how to use it in the replace, and it seems everyone online is only interested in removing/replacing commas lol.
      I also tried creating and using a variable as the replacement but also didn't work:
      $myComma = "," $myString = "COMMA" StringRegExpReplace($myString, 'COMMA', $myComma) I'm sure it's super simple if someone could point me in the right direction - thanks.
    • Skysnake
      By Skysnake
      I am tracking this topic by @LarsJ.  It is very advanced and overkill for what I am currently trying to do.
       
      Problem is this.
      Listview contains columns, one of which is right aligned and gets populated by float values, such as 123.99.  Some do not have decimals ie 124.00 and on sort gets truncated to 124.  Its obviously still the same value, but the display has reset.
      ; line below is for list VIEW ;..................................0.........1......2............ $cListView = GUICtrlCreateListView("CUSTOMER|AMOUNT|DESCRIPTION", 8, 152, 764, 279) GUICtrlSetBkColor($cListView, $GUI_BKCOLOR_LV_ALTERNATE) ; alternate between the listview background color and the listview item background color GUICtrlSetBkColor($cListView, $LVStdClr) ; Set the background color for the listview _GUICtrlListView_SetColumnWidth($cListView, 0, 120) ; -- the client name _GUICtrlListView_SetColumnWidth($cListView, 1, 90) ;-- the amount _GUICtrlListView_JustifyColumn($cListView, 1, 1) ; 1 - Text is right aligned _GUICtrlListView_SetColumnWidth($cListView, 2, 200) ; the description What I am looking for is something native and simple like a 
          _GUICtrlListView_SetColumnFormat($cListView, 1, "%.2f") ;  1 - column is stringformatted to "%.2f"
      So that after each sort it will appear as it was in the original rendering.
      Is there something like this? I have not been able to find a simple solution.

      Thanks.
      Skysnake
    • Ambient
      By Ambient
      I have tried several way sto get this to work to no avail. Any help would be appreciated. #include <ListViewConstants.au3> #include <GuiListView.au3> #include "GuiListViewEx.au3" $idItem = GUICtrlCreateListViewItem($r & " | " & $c & $adoRs.Fields("TransactionAmount").value & " | " & $Timestamp & " | " & _StringProper($adoRs.Fields("Tillid").value) & @CRLF & @CRLF & "Card Number : " & $cardnum & " " , $idListView) ConsoleWrite( "IDITEM" & $idItem) If STRINGLEFT($adoRs.Fields("TransactionAmount").value,1)= "-" Then Consolewrite(" String is Negative" & @CRLF) ;Drops in Here as expected ;GUICtrlSetColor(-1, $COLOR_RED) ; Colour line if item is negative this didn' work $TxC= _GUICtrlListView_SetTextColor($hListView, $CLR_RED) ; I also tried $TxC= _GUICtrlListView_SetTextColor(-1, 0xFF0000) CONSOLEWRITE("TEXTCOLOUR RETURNED " & $TxC & @crlf) ; This is returning True ELSE Consolewrite(" String is NOT Negative" & @CRLF) EndIf  
×