#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=y Opt( "MustDeclareVars", 1 ) #include #include #include #include "DrawItem.au3" #include "GuiListViewEx.au3" Global Const $tagMSG = "hwnd hwnd;uint message;wparam wParam;lparam lParam;dword time;int X;int Y" Global $hGui, $idListView, $hListView, $fListViewHasFocus = 0, $iItems = 1000, $iCols = 4, $iCol = 0, $aItems[$iItems][$iCols] Global $idSearch, $hSearch, $idSearchAction, $aSearch[$iItems], $iSearch = 0, $sSearch = "" Example() Func Example() ; Create GUI $hGui = GUICreate( "Show matching rows only - multiple columns", 1060, 330 ) ; Create search group GUICtrlCreateGroup( "Search", 10, 5, 1060-20, 120 ) ; Create Checkbox Local $idRegExp = GUICtrlCreateCheckbox( "Use regular expression as search string", 20, 25, 260, 20 ) GUICtrlSetState( $idRegExp, $GUI_CHECKED ) ; Create Edit control $idSearch = GUICtrlCreateEdit( "", 20, 55, 200, 20, $GUI_SS_DEFAULT_EDIT-$ES_AUTOVSCROLL-$WS_HSCROLL-$WS_VSCROLL ) GUICtrlSetData( $idSearch, "Enter search string - possibly as reg. exp." ) $hSearch = GUICtrlGetHandle( $idSearch ) $idSearchAction = GUICtrlCreateDummy() ; Create read only Edit control for number of matches Local $idCount = GUICtrlCreateEdit( "0", 230, 55, 50, 20, $GUI_SS_DEFAULT_EDIT+$ES_READONLY+$ES_RIGHT-$WS_HSCROLL-$WS_VSCROLL ) GUICtrlSetBkColor( $idCount, 0xFFFFFF ) ; Create Buttons Local $idNext = GUICtrlCreateButton( "Next match", 20, 85, 125, 25 ) Local $idPrev = GUICtrlCreateButton( "Prev match", 155, 85, 125, 25 ) GUICtrlSetState( $idNext, $GUI_DISABLE ) GUICtrlSetState( $idPrev, $GUI_DISABLE ) ; Search column Local $idComboBox = GUICtrlCreateCombo( "Search column 0", 350, 25, 200, 20 ) GUICtrlSetData( $idComboBox, "Search column 1|Search column 2|Search column 3" ) ; Close group GUICtrlCreateGroup( "", -99, -99, 1, 1 ) ; Create ListView $idListView = GUICtrlCreateListView( "", 10, 140, 1060-20, 180, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA+$LVS_OWNERDRAWFIXED, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER ) $hListView = GUICtrlGetHandle( $idListView ) ; Virtual Owner drawn Reduces flicker _GUICtrlListView_AddColumn( $hListView, "Column 0", 250 ) _GUICtrlListView_AddColumn( $hListView, "Column 1", 250 ) _GUICtrlListView_AddColumn( $hListView, "Column 2", 250 ) _GUICtrlListView_AddColumn( $hListView, "Column 3", 250 ) ; Fill array FillArray( $aItems ) _ArraySort( $aItems, 0, 0, 0, $iCol ) ; $iCol is the search column ; Set search array to display all items For $i = 0 To $iItems - 1 $aSearch[$i] = $i Next $iSearch = $iItems ; Initialize ListView GUICtrlSendMsg( $idListView, $LVM_SETITEMCOUNT, $iSearch, 0 ) ; Adjust height of GUI and ListView to fit 15 rows Local $iLvHeight = _GUICtrlListView_GetHeightToFitRows( $hListView, 15 ) WinMove( $hGui, "", Default, Default, Default, WinGetPos( $hGui )[3] - WinGetClientSize( $hGui )[1] + $iLvHeight + 150 ) WinMove( $hListView, "", Default, Default, Default, $iLvHeight ) ; Register WM_ACTIVATE message handler ; To check when GUI receives/loses focus GUIRegisterMsg( $WM_ACTIVATE, "WM_ACTIVATE" ) ; Register WM_COMMAND message handler ; To read search string from Edit control while it's typed in GUIRegisterMsg( $WM_COMMAND, "WM_COMMAND" ) ; Register WM_DRAWITEM message handler ; To display items in an owner drawn ListView GUIRegisterMsg( $WM_DRAWITEM, "WM_DRAWITEM" ) ; Register message handler to test ListView focus Local $hMessageHandler = DllCallbackRegister( "MessageHandler", "long", "int;wparam;lparam" ) Local $hMessageHook = _WinAPI_SetWindowsHookEx( $WH_MSGFILTER, DllCallbackGetPtr( $hMessageHandler ), 0, _WinAPI_GetCurrentThreadId() ) ; Show GUI GUISetState( @SW_SHOW ) ; Message loop While 1 Switch GUIGetMsg() Case $idSearchAction, $idRegExp $sSearch = GUICtrlRead( $idSearch ) If $sSearch = "" Then ; Empty search string, display all items For $i = 0 To $iItems - 1 $aSearch[$i] = $i Next $iSearch = $iItems GUICtrlSetData( $idCount, 0 ) Else ; Find rows matching search string $iSearch = 0 If GUICtrlRead( $idRegExp ) = $GUI_CHECKED Then For $i = 0 To $iItems - 1 If StringRegExp( $aItems[$i][$iCol], $sSearch ) Then ; Reg. exp. search $aSearch[$iSearch] = $i $iSearch += 1 EndIf Next Else For $i = 0 To $iItems - 1 If StringInStr( $aItems[$i][$iCol], $sSearch ) Then ; Normal search $aSearch[$iSearch] = $i $iSearch += 1 EndIf Next EndIf GUICtrlSetData( $idCount, $iSearch ) EndIf GUICtrlSendMsg( $idListView, $LVM_SETITEMCOUNT, $iSearch, 0 ) Case $idComboBox ; New search column $iCol = Int( StringRight( GUICtrlRead( $idComboBox ), 1 ) ) _ArraySort( $aItems, 0, 0, 0, $iCol ) GUICtrlSetData( $idSearch, "" ) GUICtrlSendToDummy( $idSearchAction ) Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup _WinAPI_UnhookWindowsHookEx( $hMessageHook ) GUIDelete() EndFunc ; Check when GUI receives/loses focus Func WM_ACTIVATE( $hWnd, $iMsg, $wParam, $lParam ) #forceref $iMsg, $lParam If $hWnd = $hGui Then _ $fListViewHasFocus += BitAND( $wParam, 0xFFFF ) ? 1 : -1 Return $GUI_RUNDEFMSG EndFunc ; Read search string from Edit control while it's typed in Func WM_COMMAND( $hWnd, $iMsg, $wParam, $lParam ) #forceref $hWnd, $iMsg Local Static $bEditClear = True Local $hWndFrom = $lParam Local $iCode = BitShift( $wParam, 16 ) ; High word Switch $hWndFrom Case $hSearch Switch $iCode Case $EN_CHANGE GUICtrlSendToDummy( $idSearchAction ) Case $EN_SETFOCUS If $bEditClear Then GUICtrlSetData( $idSearch, "" ) $bEditClear = False EndIf EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ; Display items in an owner drawn ListView Func WM_DRAWITEM( $hWnd, $iMsg, $wParam, $lParam ) Local Static $tRect = DllStructCreate( $tagRECT ), $pRect = DllStructGetPtr( $tRect ), $tSize = DllStructCreate( $tagSIZE ) Local Static $hBrushYellow = _WinAPI_CreateSolidBrush( 0x00FFFF ), $hBrushCyan = _WinAPI_CreateSolidBrush( 0xFFFF00 ) ; Yellow and cyan, BGR Local Static $hBrushHighLight = _WinAPI_GetSysColorBrush( $COLOR_HIGHLIGHT ), $hBrushButtonFace = _WinAPI_GetSysColorBrush( $COLOR_BTNFACE ) ; We can optimize code by removing Switch statements because the ListView is the only ownerdrawn control and only $ODA_DRAWENTIRE actions are present Local $tDrawItem = DllStructCreate( $tagDRAWITEM, $lParam ), $itemID = DllStructGetData( $tDrawItem, "itemID" ), $iState = DllStructGetData( $tDrawItem, "itemState" ), $hDC = DllStructGetData( $tDrawItem, "hDC" ), $sItemText ; Loop through columns ; $i is the column index For $i = 0 To $iCols - 1 ; Subitem rectangle DllStructSetData( $tRect, 2, $i ) ; Top DllStructSetData( $tRect, 1, $LVIR_BOUNDS ) ; Left GUICtrlSendMsg( $idListView, $LVM_GETSUBITEMRECT, $itemID, $pRect ) DllStructSetData( $tRect, 1, DllStructGetData( $tRect, 1 ) + 6 ) ; Left margin DllStructSetData( $tRect, 2, DllStructGetData( $tRect, 2 ) + 2 ) ; Top margin ; Subitem background and text color If BitAND( $iState, $ODS_SELECTED ) Then _ DllCall( "user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $tRect, "handle", $fListViewHasFocus = 1 ? $hBrushHighLight : $hBrushButtonFace ) ; _WinAPI_FillRect DllCall( "gdi32.dll", "int", "SetTextColor", "handle", $hDC, "int", BitAND( $iState, $ODS_SELECTED ) ? $fListViewHasFocus = 1 ? 0xFFFFFF : 0x000000 : 0x000000 ) ; _WinAPI_SetTextColor ; Draw subitem text $sItemText = $aItems[$aSearch[$itemID]][$i] DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText ; $i is column index ; $iCol is the search column ; Mark matching substring only if column index = search column If $i <> $iCol Then ContinueLoop ; Matching substring? If $sSearch Then Local $sMatch = StringRegExp( $sItemText, $sSearch, 1 ), $extended = @extended, $iLen = StringLen( $sMatch[0] ) ; Rectangle for matching substring DllCall( "gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sItemText, "int", $extended - $iLen - 1, "struct*", $tSize ) ; _WinAPI_GetTextExtentPoint32 DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + DllStructGetData( $tSize, "X" ) ) DllCall( "gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sMatch[0], "int", $iLen, "struct*", $tSize ) ; _WinAPI_GetTextExtentPoint32 DllStructSetData( $tRect, "Right", DllStructGetData( $tRect, "Left" ) + DllStructGetData( $tSize, "X" ) ) ; Fill rectangle with yellow or cyan (selected) background color DllCall( "user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $tRect, "handle", BitAND( $iState, $ODS_SELECTED ) ? $hBrushCyan : $hBrushYellow ) ; _WinAPI_FillRect ; Draw matching substring in rectangle DllCall( "gdi32.dll", "int", "SetTextColor", "handle", $hDC, "int", 0x000000 ) ; _WinAPI_SetTextColor DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sMatch[0], "int", $iLen, "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText EndIf Next Return $GUI_RUNDEFMSG #forceref $hWnd, $iMsg, $wParam EndFunc ; Message handler to test ListView focus Func MessageHandler( $nCode, $wParam, $lParam ) #forceref $nCode, $wParam Local $tMsg = DllStructCreate( $tagMSG, $lParam ), $iMsg = DllStructGetData( $tMsg, "message" ) If $iMsg = $WM_LBUTTONDOWN Or $iMsg = $WM_RBUTTONDOWN Then $fListViewHasFocus = DllStructGetData( $tMsg, "hwnd" ) = $hListView ? 1 : 0 EndFunc ; Fill array with random strings 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 $iCols - 1 For $j = 0 To $iItems - 1 $s = $aLetters[Random(0,25,1)] For $k = 1 To Random(10,30,1) $s &= $aLetters[Random(0,25,1)] Next $aItems[$j][$i] = $s Next Next EndFunc