ListView search / filter Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
gallaxhar
Posts: 143
Joined: 03 Sep 2014, 06:35

ListView search / filter

20 Feb 2016, 05:23

I'm trying to create a way to filter a one-column listview control based on the contents of an edit control, finding the rows which start with or completely match the contents of the edit control, and only showing those rows in the listview.

Similar to this behavior from AutoCAD:
http://i.imgur.com/S2MIjMG.gifv

I know to place the code in the edit boxes g-label subroutine, so it updates the ListView as the user types.

I also found Rajat's old 320mph, NODE, and other names for his fast, but extremely complex and obfuscated search utility. It's also used in Lintalist, Columbus search, and CSVQF (CSV Quick Filter).

I also found just_me's LV_EX library which has a function that returns an object for the matched rows/columns, but again the syntax is weird, and unfortunately if I can't understand it I've found in the past that I can't maintain or really improve/build upon the script.

So I'm looking for the most AHK-vanilla or plain way to update/filter a listview's rows based on an edit control's contents, as the user types, even at the cost of slower performance (but hopefully not painfully slow). I expect my listview to contain about 1000 rows, all in one column, and each column containing no more than probably 5 words.

Here is what I have so far: (attention to the code snippet "; Edit1 Control g-label Subroutine")

Code: Select all

; ListView like AutoCAD's Dynamic Input and then some
; ===================================================
; Example GIF: http://i.imgur.com/S2MIjMG.gifv


; Script Settings
; ---------------
#Persistent
#SingleInstance, Force
#NoEnv
CoordMode, Mouse, Screen


; Run the script with maximum speed
; ---------------------------------
SetBatchLines, -1 ; <<<<<


; Make the Gui ListView1 resides in invisible
; -------------------------------------------
Gui, Margin, 0, 0
Gui, +LastFound
Gui, Color, EEAA99
WinSet, TransColor, EEAA99
Gui, -Caption


; Get current mouse coordinates
; -----------------------------
MouseGetPos, MousePosX, MousePosY


; Offset mouse coordinates for Edit1's position
; ---------------------------------------------
MousePosX:=MousePosX+20
MousePosY:=MousePosY+8


; Create the Edit1 control
; ------------------------
Gui, Add, Edit, r1 hwndEdit1Hwnd vEdit1 w0 gEdit1Subroutine Uppercase ; <<<< get the handle to the control


; Create ListView1 control
; ------------------------
Gui, Add, ListView, vListView1 w50 -Hdr -Multi -WantF2 R7 Report,1


; Populate ListView1 control
; --------------------------
Loop, 50
{
	LV_Add(,A_Index)
}
LV_Add(,"Lorem ipsum dolor sit amet")


; AutoSize ListView1 Columns
; --------------------------
LV_ModifyCol(1,"AutoHdr")


; AutoSize ListView1 Control
; --------------------------
Gui, +LastFound ; activate Gui window
totalWidth := 0 ; initialize ListView width variable
; get columns' widths
Loop % LV_GetCount("Column")
{
	SendMessage, 4125, A_Index - 1, 0, SysListView321 ; 4125 is LVM_GETCOLUMNWIDTH.
	totalWidth := totalWidth + ErrorLevel
}


; Resize ListView1 control
; ------------------------
GuiControl, Move, ListView1, % "W" . totalWidth + 22


; Show ListView1Gui
; -----------------
Gui,Show,x%MousePosX% y%MousePosY% AutoSize,ListView1Gui


; Monitor Edit1 Control Updates
; -----------------------------
OnMessage(0x0111, "CheckEditUpdate") ; 0x0111 is WM_COMMAND


; End of AutoExec
; ---------------
Return


; Edit1 Control g-label Subroutine
; --------------------------------
Edit1Subroutine:
GuiControlGet, Edit1 ; retrieve Edit1 contents
If (Edit1="")	{
	Gui, Destroy
	return
	}
Else	{
	; Some code that compares the Edit1 control's contents to every row's contents in the listview, and returns the row numbers that begin with that string
	; Then updates the listview to only show those matched rows
	}	
Gui, Show, Autosize
Return


; Message monitor for WM_COMMAND -> EN_UPDATE notifications
; WM_COMMAND (0x0111)   -> msdn.microsoft.com/en-us/library/ms647591(v=vs.85).aspx
;                          wParam:  high word = notification code, low word = control identifier
;                          lParam:  handle to the control window
; EN_UPDATE  (0x0400)   -> msdn.microsoft.com/en-us/library/bb761687(v=vs.85).aspx
; ---------------------------------------------------------
CheckEditUpdate(wParam, lParam, Msg, hWnd) {
   Global Edit1Hwnd ; edit control's handle
   If (lParam = Edit1Hwnd) && ((wParam >> 16) = 0x0400) {
      GuiControlGet, Content, , %lParam%
      Gui, New
      Gui, Add, Edit, hwndHCTL Uppercase, %Content%
      GuiControlGet, P, Pos, %HCTL%
      Gui, Destroy
      GuiControl, Move, %lParam%, % "w" . (PW)
   }
}


; Hotkeys
; -------
#IfWinActive, ListView1Gui

; Enable endless up navigation with arrow keys
$Up::
PreviousPos:=LV_GetNext()
If (PreviousPos = 0) ; exception, focus is not on listview this will allow you to jump to last item via UP key
	{
	 ControlSend, SysListview321, {End}, ListView1Gui
	 Return
	}
ControlSend, SysListview321, {Up}, ListView1Gui
ItemsInList:=LV_GetCount()
ChoicePos:=PreviousPos-1
If (ChoicePos <= 1)
	ChoicePos = 1
If (ChoicePos = PreviousPos)
    ControlSend, SysListview321, {End}, ListView1Gui
Return

; Enable endless down navigation with arrow keys
$Down::
PreviousPos:=LV_GetNext()
ControlSend, SysListview321, {Down}, ListView1Gui
ItemsInList:=LV_GetCount()
ChoicePos:=PreviousPos+1
If (ChoicePos > ItemsInList)
	ChoicePos := ItemsInList
If (ChoicePos = PreviousPos)
    ControlSend, SysListview321, {Home}, ListView1Gui
Return

; Enable up navigation with scroll wheel
$WheelUp::
ControlSend, SysListview321, {Up}, ListView1Gui
Return

; Enable down navigation with scroll wheel
$WheelDown::
ControlSend, SysListview321, {Down}, ListView1Gui
Return

#IfWinActive


; ESC Key Closes Script
; ---------------------
GuiEscape: ; ESC
GuiClose: ; Program is closed
ExitApp
Last edited by gallaxhar on 20 Feb 2016, 11:48, edited 2 times in total.
listview-or-box

Re: ListView partial search / filter

20 Feb 2016, 05:52

Code: Select all

; ListView like AutoCAD's Dynamic Input and then some
; ===================================================
; Example GIF: http://i.imgur.com/S2MIjMG.gifv
 
 
; Script Settings
; ---------------
#Persistent
#SingleInstance, Force
#NoEnv
CoordMode, Mouse, Screen

loop, 50
	listdata .= A_Index ","
listdata:=RTrim(listdata,",")	
 
 
; Run the script with maximum speed
; ---------------------------------
SetBatchLines, -1 ; <<<<<
 
 
; Make the Gui ListView1 resides in invisible
; -------------------------------------------
Gui, LV:New
Gui, Margin, 0, 0
Gui, +LastFound hwndLVGui
Gui, Color, EEAA99
WinSet, TransColor, EEAA99
Gui, -Caption
 
 
; Get current mouse coordinates
; -----------------------------
MouseGetPos, MousePosX, MousePosY
 
 
; Offset mouse coordinates for Edit1's position
; ---------------------------------------------
MousePosX:=MousePosX+20
MousePosY:=MousePosY+8
 
 
; Create the Edit1 control
; ------------------------
Gui, Add, Edit, r1 hwndEdit1Hwnd vEdit1 w0 gEdit1Subroutine Uppercase ; <<<< get the handle to the control
 
 
; Create ListView1 control
; ------------------------
Gui, Add, ListView, vListView1 w50 -Hdr -Multi -WantF2 R7 Report,1

LV_Delete()
Gosub, LVUpdate 
 
 
; Show ListView1Gui
; -----------------
Gui,Show,x%MousePosX% y%MousePosY% AutoSize,ListView1Gui
 
 
; Monitor Edit1 Control Updates
; -----------------------------
OnMessage(0x0111, "CheckEditUpdate") ; 0x0111 is WM_COMMAND
 
 
; End of AutoExec
; ---------------
Return

LVUpdate:
Gui, LV:Default
; Populate ListView1 control
; --------------------------
Loop, parse, listdata, CSV
{
	LV_Add(,A_LoopField)
}
LV_Add(,"Lorem ipsum dolor sit amet")
 
 
; AutoSize ListView1 Columns
; --------------------------
LV_ModifyCol(1,"AutoHdr")
 
 
; AutoSize ListView1 Control
; --------------------------
Gui, +LastFound ; activate Gui window
totalWidth := 0 ; initialize ListView width variable
; get columns' widths
Loop % LV_GetCount("Column")
{
	SendMessage, 4125, A_Index - 1, 0, SysListView321 ; 4125 is LVM_GETCOLUMNWIDTH.
	totalWidth := totalWidth + ErrorLevel
}
 
 
; Resize ListView1 control
; ------------------------
GuiControl, Move, ListView1, % "W" . totalWidth + 22
Return 
 
; Edit1 Control g-label Subroutine
; --------------------------------
Edit1Subroutine:
GuiControlGet, Edit1 ; retrieve Edit1 contents
If (Edit1="")	{
	Gui, Destroy
	return
	}
Else	{
	; Some code that compares the Edit1 control's contents to every row's contents in the listview, and returns the row numbers that begin with that string
	; Then updates the listview to only show those matched rows
	}	
Gui, Show, Autosize
Return
 
 
; Message monitor for WM_COMMAND -> EN_UPDATE notifications
; WM_COMMAND (0x0111)   -> msdn.microsoft.com/en-us/library/ms647591(v=vs.85).aspx
;                          wParam:  high word = notification code, low word = control identifier
;                          lParam:  handle to the control window
; EN_UPDATE  (0x0400)   -> msdn.microsoft.com/en-us/library/bb761687(v=vs.85).aspx
; ---------------------------------------------------------
CheckEditUpdate(wParam, lParam, Msg, hWnd) {
   Global Edit1Hwnd,listdata ; edit control's handle
   If (lParam = Edit1Hwnd) && ((wParam >> 16) = 0x0400) {
      GuiControlGet, Content, , %lParam%
      Gui, New
      Gui, Add, Edit, hwndHCTL Uppercase, %Content%
      GuiControlGet, P, Pos, %HCTL%
      Gui, Destroy
      GuiControl, Move, %lParam%, % "w" . (PW)
      Gui, LV:Default
      LV_Delete()
      If (Content = "")
      	Gosub, LVUpdate
      else
      	{
	      loop, parse, listdata, CSV
	      	if InStr(A_LoopField,content)
	      		LV_Add(, A_LoopField)
      	}	
      
   }
}
 
 
; Hotkeys
; -------
#IfWinActive, ListView1Gui
 
; Enable endless up navigation with arrow keys
$Up::
PreviousPos:=LV_GetNext()
If (PreviousPos = 0) ; exception, focus is not on listview this will allow you to jump to last item via UP key
	{
	 ControlSend, SysListview321, {End}, ListView1Gui
	 Return
	}
ControlSend, SysListview321, {Up}, ListView1Gui
ItemsInList:=LV_GetCount()
ChoicePos:=PreviousPos-1
If (ChoicePos <= 1)
	ChoicePos = 1
If (ChoicePos = PreviousPos)
    ControlSend, SysListview321, {End}, ListView1Gui
Return
 
; Enable endless down navigation with arrow keys
$Down::
PreviousPos:=LV_GetNext()
ControlSend, SysListview321, {Down}, ListView1Gui
ItemsInList:=LV_GetCount()
ChoicePos:=PreviousPos+1
If (ChoicePos > ItemsInList)
	ChoicePos := ItemsInList
If (ChoicePos = PreviousPos)
    ControlSend, SysListview321, {Home}, ListView1Gui
Return
 
; Enable up navigation with scroll wheel
$WheelUp::
ControlSend, SysListview321, {Up}, ListView1Gui
Return
 
; Enable down navigation with scroll wheel
$WheelDown::
ControlSend, SysListview321, {Down}, ListView1Gui
Return
 
#IfWinActive
 
 
; ESC Key Closes Script
; ---------------------
GuiEscape: ; ESC
GuiClose: ; Program is closed
ExitApp
:?:
listview-or-box

Re: ListView partial search / filter

20 Feb 2016, 05:57

The above uses InStr but if you need to find multiple partial strings independent of the order they appear in ('foo bar' and 'bar foo' has the same result) you can look at the RegExMatch solution here L178 to L182 from pAHKlight (Google for it, its on GH) in your case replace 'Search' with 'Content' and it should work.
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ListView partial search / filter

20 Feb 2016, 07:06

... finding the rows which start with or completely match the contents of the edit control ...
I also found just_me's LV_EX library which has a function that returns an object for the matched rows/columns, but again the syntax is weird, ...
weird? :shock:

Your LV has only one column, so the proper function would be LV_EX_FindString(HLV, Str, Start := 0, Partial := False). No object and no weird syntax. ;)
But it might not be useful in this case. If you want to perform backspacing, the LV will most likely not contain all matching items any more.

Also, if you want to match only at the start of the item's text, I'd modify theInStr() provided by list-view-or-box as follows:

Code: Select all

if (InStr(A_LoopField,content) = 1)
gallaxhar
Posts: 143
Joined: 03 Sep 2014, 06:35

Re: ListView search / filter

20 Feb 2016, 09:51

Thank you guys, because of your replies I gained some more things to search for and try, it looks like the following code from this post will work, but I'm too tired (cant think) to try until I sleep https://autohotkey.com/board/topic/3765 ... view-rows/

I think it uses two listviews and deletes one, makes another one, but it seems to not flicker, and supports backspaces
it's also really short but plain code which is attractive, uses instr like you guys did

listview-or-box, again, too tired to figure out why at the moment, but your code didn't work with alphabetical letters, only the numbers

Code: Select all

#SingleInstance force

#NoEnv

SetBatchLines, -1



Gui, Add, Text,,Search:

Gui, Add, Edit, w400 vA_SearchTerm gSearch

Gui, Add, ListView, grid r20 w400 vLV1, FileName

Gui, Add, ListView, grid r20 w400 vLV2 xp yp, FileName

Loop, %A_Desktop%\*.*

  LV_Add("",A_LoopFileName)

LV_ModifyCol()



Gui, Show

return

GuiClose:

ExitApp



Search:

Gui, Submit, NoHide

If (A_SearchTerm != "")

{

 Gui, ListView, LV1

 LV_Delete()

 Gui, ListView, LV2

 Loop,% LV_GetCount()

 {

  Gui, ListView, LV2

  LV_GetText(RetrievedText, A_Index)

  If InStr(RetrievedText, A_SearchTerm)

  {

   Gui, ListView, LV1

   LV_Add("",RetrievedText)

  }

 }

 GuiControl, Hide, LV2

 GuiControl, Show, LV1

}

Else

{

 GuiControl, Hide, LV1

 GuiControl, Show, LV2

}

return
gallaxhar
Posts: 143
Joined: 03 Sep 2014, 06:35

Re: ListView search / filter

20 Feb 2016, 09:54

@just me
while you were gone and after I found LV_EX, I went to the ahk irc and sjc1 or whatever his username is looked at the LV_EX_FindStringEx, remarked it was too weird for him to figure out what to do with the result of the function, him being vastly better at AHK than me, I assumed it was weird code. It's too over my head for me to actually know if it's "weird" or not. I'd say it's definitely not as weird as rajat's though.. that stuff is crazy.
listview-or-box

Re: ListView search / filter

20 Feb 2016, 09:58

My script above also supports backspaces and your 2nd script also works for me so not sure what you mean. The two listview methods are useful if you have very big listviews and you clear the search field often, that way you can quickly show the listview again without building it up again.
gallaxhar
Posts: 143
Joined: 03 Sep 2014, 06:35

Re: ListView search / filter

20 Feb 2016, 10:03

movie: http://i.imgur.com/awHyLKL.gifv

The only text row in the listview right now is Lorem ipsum dolor sit amet

It's probably a simple fix but I haven't looked yet, and I just randomly googled hide/show listview rows as it occurred to me that might work and found that code i pasted last
listview-or-box

Re: ListView search / filter

20 Feb 2016, 10:22

That is because lorem ipsum is NOT part of the listdata variable. That variable is built at the top just for testing purposes.

If you replace listdata:=RTrim(listdata,",") on line 15 or so with listdata.= "lorem ipsum" it will of course work as now lorem is part of the variable that is being parsed to search for what you've typed.
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ListView search / filter  Topic is solved

20 Feb 2016, 10:25

Is this one fast enough for you?

Code: Select all

#NoEnv
#SingleInstance force
SetBatchLines, -1

LVArray := []
Gui, Add, Text, ,Search:
Gui, Add, Edit, w400 vSearchTerm gSearch
Gui, Add, ListView, grid r20 w400 vLV, FileName
Loop, %A_WinDir%\System32\*.*
{
   LV_Add("", A_LoopFileName)
   LVArray.Push(A_LoopFileName)
}
TotalItems := LVArray.Length()
LV_ModifyCol()
Gui, Add, StatusBar, , % "   " . TotalItems . " of " . TotalItems . " Items"
Gui, Show, , ListView
Return

GuiClose:
ExitApp

Search:
GuiControlGet, SearchTerm
GuiControl, -Redraw, LV
LV_Delete()
For Each, FileName In LVArray
{
   If (SearchTerm != "")
   {
      If (InStr(FileName, SearchTerm) = 1) ; for matching at the start
      ; If InStr(FileName, SearchTerm) ; for overall matching
         LV_Add("", FileName)
   }
   Else
      LV_Add("", FileName)
}
Items := LV_GetCount()
SB_SetText("   " . Items . " of " . TotalItems . " Items")
GuiControl, +Redraw, LV
Return
gallaxhar
Posts: 143
Joined: 03 Sep 2014, 06:35

Re: ListView search / filter

20 Feb 2016, 10:28

@listview or box
strange, so you're putting all of the text from all of the rows into a single variable, listdata, and then testing if the searchstring is inside that variable, and if it is, somehow getting the row numbers for the rows?
----
@just me
yes that latest example seems instant to me

all that i've found and seen so far has parts I really just dont understand, but the last one seems to have the least amount of parts I don't understand

in the end I'm going to try and make this open source for a bunch of barely-computer-literate people (autocad people :-) ), so that's also part of the reason im trying to keep things stupid-simple, there's a better chance someone can help improve it, or that i'll be able to remember what stuff does later if i improve it

---
@both
thanks for all of your help!

edit 4:
ack, didnt realize you both replied within such a close timeframe lol I thought it was the same person in two posts
shows how tired I am
gallaxhar
Posts: 143
Joined: 03 Sep 2014, 06:35

Re: ListView search / filter

20 Feb 2016, 10:36

@just me
man that last example is killer
almost 4000 items instantly searched in 41 lines of very readable code
seems like a winner
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ListView search / filter

20 Feb 2016, 10:41

If you don't understand parts of my sample, ask please. But I have to leave now, so I'll answer tomorrow morning (German time).
gallaxhar
Posts: 143
Joined: 03 Sep 2014, 06:35

Re: ListView search / filter

20 Feb 2016, 10:50

I learned the pieces I didn't understand with the docs and Geekdude/phaleth in IRC
Terka
Posts: 157
Joined: 05 Nov 2015, 04:59

Re: [Solved] ListView search / filter

30 Nov 2017, 07:44

Hi, can you please help me modigy the code of @just me so i can choose one of the fields and copy its name to a variable?
garry
Posts: 3795
Joined: 22 Dec 2013, 12:50

Re: [Solved] ListView search / filter

30 Nov 2017, 15:26

@Terka
copy selected row to clipboard with rightclick

Code: Select all

;- modify this above
Gui, Add, ListView, grid r20 w400 vLV gLV1 altsubmit, FileName
;....

LV1:
if A_GuiEvent = RightClick
{
clipboard=
LV_GetText(C1,A_EventInfo,1)
cx=%A_WinDir%\System32\%c1%
clipboard=%cx%
msgbox,%clipboard%
}
return
gmanhunt
Posts: 18
Joined: 14 Mar 2018, 01:30

Re: ListView search / filter

16 Jul 2019, 03:14

just me wrote:
20 Feb 2016, 10:25
Is this one fast enough for you?

Code: Select all

#NoEnv
#SingleInstance force
SetBatchLines, -1

LVArray := []
Gui, Add, Text, ,Search:
Gui, Add, Edit, w400 vSearchTerm gSearch
Gui, Add, ListView, grid r20 w400 vLV, FileName
Loop, %A_WinDir%\System32\*.*
{
   LV_Add("", A_LoopFileName)
   LVArray.Push(A_LoopFileName)
}
TotalItems := LVArray.Length()
LV_ModifyCol()
Gui, Add, StatusBar, , % "   " . TotalItems . " of " . TotalItems . " Items"
Gui, Show, , ListView
Return

GuiClose:
ExitApp

Search:
GuiControlGet, SearchTerm
GuiControl, -Redraw, LV
LV_Delete()
For Each, FileName In LVArray
{
   If (SearchTerm != "")
   {
      If (InStr(FileName, SearchTerm) = 1) ; for matching at the start
      ; If InStr(FileName, SearchTerm) ; for overall matching
         LV_Add("", FileName)
   }
   Else
      LV_Add("", FileName)
}
Items := LV_GetCount()
SB_SetText("   " . Items . " of " . TotalItems . " Items")
GuiControl, +Redraw, LV
Return
I hate to be the guy who revives dead threads, but I kinda need help with something.

How do I preserve checkboxes? I notice if I clear the edit box my checkbox selection will reset as well.
red_sun
Posts: 19
Joined: 12 Jul 2019, 05:22

Re: [Solved] ListView search / filter

16 Jul 2019, 08:34

I hate to be the guy who revives dead threads
:problem: this post is marked as solved so only by accident forum users will open it …….. like me ;)

Can you create a new post and give some info what you want to do , because after clearing the edit it is logical that the selection is also reset.
If you just want to freeze the result and still ( for some mystery reason ) want the clear the edit it is easy if you add a condition before a new execution of the "search" label.

Here is an example that blocks changing the results when the Shift lock key is on ( or Capslock ) btw I do not understand what you mean by checkboxes in ahk they mean this:
https://www.autohotkey.com/docs/commands/GuiControls.htm#Checkbox

Code: Select all

;       added condition if Shiftlock no update of results)

#NoEnv
#SingleInstance force
SetBatchLines, -1

LVArray := []
Gui, Add, Text, ,Search:
Gui, Add, Edit, w400 vSearchTerm gSearch
Gui, Add, ListView, grid r20 w400 vLV, FileName
Loop, %A_WinDir%\System32\*.*
{
   LV_Add("", A_LoopFileName)
   LVArray.Push(A_LoopFileName)
}
TotalItems := LVArray.Length()
LV_ModifyCol()
Gui, Add, StatusBar, , % "   " . TotalItems . " of " . TotalItems . " Items"
Gui, Show, , ListView
Return

GuiClose:
ExitApp

Search:
if getkeystate("CapsLock","T")
return

GuiControlGet, SearchTerm
GuiControl, -Redraw, LV
LV_Delete()
For Each, FileName In LVArray
{
   If (SearchTerm != "")
   {
      If (InStr(FileName, SearchTerm) = 1) ; for matching at the start
      ; If InStr(FileName, SearchTerm) ; for overall matching
         LV_Add("", FileName)
   }
   Else
      LV_Add("", FileName)
}
Items := LV_GetCount()
SB_SetText("   " . Items . " of " . TotalItems . " Items")
GuiControl, +Redraw, LV
Return
gmanhunt
Posts: 18
Joined: 14 Mar 2018, 01:30

Re: [Solved] ListView search / filter

16 Jul 2019, 09:17

red_sun wrote:
16 Jul 2019, 08:34
I hate to be the guy who revives dead threads
:problem: this post is marked as solved so only by accident forum users will open it …….. like me ;)

Can you create a new post and give some info what you want to do , because after clearing the edit it is logical that the selection is also reset.
If you just want to freeze the result and still ( for some mystery reason ) want the clear the edit it is easy if you add a condition before a new execution of the "search" label.

Here is an example that blocks changing the results when the Shift lock key is on ( or Capslock ) btw I do not understand what you mean by checkboxes in ahk they mean this:
https://www.autohotkey.com/docs/commands/GuiControls.htm#Checkbox

Code: Select all

;       added condition if Shiftlock no update of results)

#NoEnv
#SingleInstance force
SetBatchLines, -1

LVArray := []
Gui, Add, Text, ,Search:
Gui, Add, Edit, w400 vSearchTerm gSearch
Gui, Add, ListView, grid r20 w400 vLV, FileName
Loop, %A_WinDir%\System32\*.*
{
   LV_Add("", A_LoopFileName)
   LVArray.Push(A_LoopFileName)
}
TotalItems := LVArray.Length()
LV_ModifyCol()
Gui, Add, StatusBar, , % "   " . TotalItems . " of " . TotalItems . " Items"
Gui, Show, , ListView
Return

GuiClose:
ExitApp

Search:
if getkeystate("CapsLock","T")
return

GuiControlGet, SearchTerm
GuiControl, -Redraw, LV
LV_Delete()
For Each, FileName In LVArray
{
   If (SearchTerm != "")
   {
      If (InStr(FileName, SearchTerm) = 1) ; for matching at the start
      ; If InStr(FileName, SearchTerm) ; for overall matching
         LV_Add("", FileName)
   }
   Else
      LV_Add("", FileName)
}
Items := LV_GetCount()
SB_SetText("   " . Items . " of " . TotalItems . " Items")
GuiControl, +Redraw, LV
Return
Hello,

Yeah, my bad, didn't give enough information.
English is not my first language, I'm not very good at it so I'm going to break it down in short sentences.

I have a ListView with the 'checked' option enabled, which creates a checkbox for every row.

The ListView is filled with staff names and ID. Going through hundreds of names will be tedious, especially if I want to select only a couple of rows.

Checkbox is great for this since won't accidentally lose my selection, but there's still the problem with going through hundreds of names.

The filter script by just me worked great to filter through the names, but I also lose my checkbox.

So my workaround right now is:
Set up a g-Label and AltSubmit for my ListView.
If A_GuiEvent == "I" && ErrorLevel == "C", read the text and push {id: name} immediately into an array.
If the same selection exists in the array (I used ID since their values are unique), then remove it from the array.

It's not without some wonkiness after filtering the list/losing the checkbox selection.
It works, but I was wondering if there's a better way to do it.

Thanks!
red_sun
Posts: 19
Joined: 12 Jul 2019, 05:22

Re: [Solved] ListView search / filter

16 Jul 2019, 12:06

Now I see what you mean by checkboxes ! But still I think it is best to create a new post with listview in the title that would entice some experts to it :)

I am not very familiar with listviews but I found a interesting one here:
https://autohotkey.com/board/topic/37651-how-to-hiding-and-showing-back-listview-rows/

The concept is quite nice but I think your solution is safer ( but you loose the checkboxes ) I gave it a quick try to see if it has a chance of working.The drawback is that in search you have to fill in till you are left with only one result ( in this code ….) but the positive is that you keep the original with the checkboxes.Maybe it gives some inspiration …...….. :idea:

Code: Select all


#SingleInstance force

#NoEnv

SetBatchLines, -1

LVArray := ["ada","hina","sakura","tomo","mei"]

Gui, Add, Text,,Search:
Gui, Add, Edit, w400 vA_SearchTerm gSearch 
Gui, Add, ListView,  r20 w400 vLV1 checked AltSubmit gselect, name
Gui, Add, ListView, grid r20 w400 vLV2 xp yp checked, name

For k, name In LVArray
  {
  LV_Add("", name)
  
  }
LV_ModifyCol()
Gui, Show
return

select:
if regexmatch(A_guievent,"C|c")
    {
      ;status_check:=errorlevel="c"?"-check":"check"
      status_check:="check"  ; always check an item
      GuiControl, Hide, LV1
      guicontrol, show,lV2
      Gui, listview, lv2
      LV_Modify(status, status_check)
    }
return

Search:
Gui, Submit, NoHide

If (A_SearchTerm != "")
  {
   Gui, ListView, LV1
   LV_Delete()
   Gui, ListView, LV2
   Loop,% LV_GetCount()
       {
        Gui, ListView, LV2
        LV_GetText(RetrievedText, A_Index)
        If InStr(RetrievedText, A_SearchTerm)
          {
           status:=A_Index
           tooltip % A_Index
           Gui, ListView, LV1
           LV_Add("",RetrievedText)
          }
       }
   GuiControl, Hide, LV2
   GuiControl, Show, LV1
  }
  Else
    {
     GuiControl, Hide, LV1
     GuiControl, Show, LV2
    }
return

GuiClose:
ExitApp

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: macromint, peter_ahk, Rauvagol, Spawnova, wineguy and 280 guests