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