#include #include Opt("MustDeclareVars", 1) Global $hGui, $hEdit, $idEditSearch, $hLV, $iItems = 1000, $aItems[$iItems][3], $aSearch[$iItems], $iSearch = 0, $iRows = $iItems Global Const $hKernel32Dll = DllOpen("kernel32.dll") Global $iSortCol = -1, $tIndex Example() Func Example() ; Create GUI $hGui = GUICreate("Gui", 600, 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() ; Create ListView Virtual listview Global $idLV = GUICtrlCreateListView("", 10, 40, 600 - 20, 200 - 20, $LVS_OWNERDATA, BitOR($LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES)) $hLV = GUICtrlGetHandle($idLV) _GUICtrlListView_AddColumn($hLV, "Item", 220) _GUICtrlListView_AddColumn($hLV, "Sub1", 125) _GUICtrlListView_AddColumn($hLV, "Sub2", 130) Local $hHeader = _GUICtrlListView_GetHeader($hLV) Local $iSortColPrev = -1, $iSortArrow ; 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_Search") ; Handle $WM_NOTIFY messages from ListView ; Necessary to display the rows in a virtual ListView GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState(@SW_SHOW) FillArray($aItems) Local $tStrings1 = DllStructCreate("uint[" & $iRows & "]"), $pStrings1 = DllStructGetPtr($tStrings1) Local $tStrings2 = DllStructCreate("uint[" & $iRows & "]"), $pStrings2 = DllStructGetPtr($tStrings2) Local $tStrings3 = DllStructCreate("uint[" & $iRows & "]"), $pStrings3 = DllStructGetPtr($tStrings3) SortStrings($aItems, $iRows, 0, $pStrings1, $tStrings1) SortStrings($aItems, $iRows, 1, $pStrings2, $tStrings2) SortStrings($aItems, $iRows, 2, $pStrings3, $tStrings3) $tIndex = $tStrings1 ; 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) 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 $aSearch[$iSearch] = $i $iSearch += 1 EndIf Next EndIf ; Display items GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iSearch, 0) Case $idLV $iSortCol = GUICtrlGetState($idLV) Switch $iSortCol Case 0 $tIndex = $tStrings1 Case 1 $tIndex = $tStrings2 Case 2 $tIndex = $tStrings3 EndSwitch _GUICtrlHeader_SetItemFormat($hHeader, $iSortColPrev, $HDF_STRING) _GUICtrlHeader_SetItemFormat($hHeader, $iSortCol, $HDF_STRING + $HDF_SORTUP) GUICtrlSendMsg($idLV, $LVM_SETSELECTEDCOLUMN, $iSortCol, 0) DllCall("user32.dll", "int", "InvalidateRect", "hwnd", $hLV, "int", 0, "int", 1) $iSortColPrev = $iSortCol Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd DllClose($hKernel32Dll) GUIDelete() EndFunc ;==>Example Func FillArray(ByRef $aItems) Local $aLetters[26] = ['A', 'B', 'C', 'D', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', _ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'], $s For $i = 0 To $iItems - 1 $s = $aLetters[Random(0, 25, 1)] For $j = 1 To Random(10, 30, 1) $s &= $aLetters[Random(0, 25, 1)] Next $aItems[$i][0] = $s $aItems[$i][1] = "AAA" & $i $aItems[$i][2] = "BBB" & $i + 2 Next EndFunc ;==>FillArray Func SortStrings(ByRef $aItems, $iRows, $iCol, $pIndex, $tIndex) Local $s, $lo, $hi, $mi For $j = 0 To $iRows - 1 $s = $aItems[$j][$iCol] ; Binary search $lo = 0 $hi = $j - 1 While $lo <= $hi $mi = Int(($lo + $hi) / 2) If StringCompare($s, $aItems[DllStructGetData($tIndex, 1, $mi + 1)][$iCol]) < 0 Then $hi = $mi - 1 Else $lo = $mi + 1 EndIf WEnd ; Make space for the new value If $j > $mi Then _ DllCall($hKernel32Dll, "none", "RtlMoveMemory", "struct*", $pIndex + ($mi + 1) * 4, "struct*", $pIndex + $mi * 4, "ulong_ptr", ($j - $mi) * 4) ; Insert new value DllStructSetData($tIndex, 1, $j, $mi + 1 + ($lo = $mi + 1)) Next EndFunc ;==>SortStrings Func WM_COMMAND_Search($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 ;==>WM_COMMAND_Search 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 $iItem = DllStructGetData($tNMLVDISPINFO, "Item") Local $iSubItem = DllStructGetData($tNMLVDISPINFO, "SubItem") ;Search Global $sItem = $aItems[$aSearch[$iItem]][$iSubItem] ;Sort ;Local $sItem = $aItems[DllStructGetData($tIndex, 1, $iItem + 1)][$iSubItem] DllStructSetData($tText, 1, $sItem) DllStructSetData($tNMLVDISPINFO, "Text", $pText) DllStructSetData($tNMLVDISPINFO, "TextMax", StringLen($sItem)) EndIf Case $LVN_COLUMNCLICK Local $tInfo = DllStructCreate($tagNMLISTVIEW, $lParam) Local $iCol = DllStructGetData($tInfo, "SubItem") _ArraySort($aItems, 0, 0, 0, $iCol) GUICtrlSendMsg($hLV, $LVM_REDRAWITEMS, 0, $iSearch - 1) ConsoleWrite("Column " & $iCol & @CRLF) EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY