Что нового

Маркировка найденого при поиске в виртуальном 2D ListView

liond66

Новичок
Сообщения
52
Репутация
1
Здравствуйте.
Вот здесь https://www.autoitscript.com/forum/topic/179112-incremental-search-in-owner-drawn-listview/
я увидел довольно оригинальную функцию маркировки жёлтеньким найденых букв.



Взял оригинальный пример "2) Show matching rows only.au3". Но там проблема больших маленьких букв.
Вот код:
Код:
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <Array.au3>
#include "DrawItem.au3"
#include "GuiListViewEx.au3"
#include <WinAPI.au3>

Opt( "MustDeclareVars", 1 )
Opt( "GUIResizeMode", $GUI_DOCKALL )

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, $aItems[$iItems]
Global $idSearch, $hSearch, $idSearchAction, $aSearch[$iItems], $iSearch = 0, $sSearch = ""

Example()


Func Example()
	; Create GUI
	$hGui = GUICreate( "Show matching rows only", 300, 330 )

	; Create search group
	GUICtrlCreateGroup( "Search", 10, 5, 300-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 )

	; Close group
	GUICtrlCreateGroup( "", -99, -99, 1, 1 )

	; Create ListView
	$idListView = GUICtrlCreateListView( "", 10, 140, 300-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, "Items",  250 )

	; Fill array
	FillArray( $aItems )
	_ArraySort( $aItems, 0, 0, 0, 0, 1 )

	; 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], $sSearch ) Then ; Reg. exp. search
								$aSearch[$iSearch] = $i
								$iSearch += 1
							EndIf
						Next
					Else
						For $i = 0 To $iItems - 1
							If StringInStr( $aItems[$i], $sSearch ) Then ; Normal search
								$aSearch[$iSearch] = $i
								$iSearch += 1
							EndIf
						Next
					EndIf
					GUICtrlSetData( $idCount, $iSearch )
				EndIf
				GUICtrlSendMsg( $idListView, $LVM_SETITEMCOUNT, $iSearch, 0 )

			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 )
	#forceref $hWnd, $iMsg, $wParam
	Local Static $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 )

	Local $tDrawItem = DllStructCreate( $tagDRAWITEM, $lParam )
	If DllStructGetData( $tDrawItem, "CtlType" ) <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG

	Switch DllStructGetData( $tDrawItem, "CtlID" )
		Case $idListView
			Switch DllStructGetData( $tDrawItem, "itemAction" )
				Case $ODA_DRAWENTIRE
					Local $iIndex = DllStructGetData( $tDrawItem, "itemID" ), $iState = DllStructGetData( $tDrawItem, "itemState" ), $hDC = DllStructGetData( $tDrawItem, "hDC" ), $sItemText = $aItems[$aSearch[$iIndex]]

					; Item rectangle
					Local $tRect = DllStructCreate( $tagRECT, DllStructGetPtr( $tDrawItem, "Left" ) )
					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 4 ) ; 4 pixel left margin for background

					; Item 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 item text
					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 2 ) ; Plus 2 pixel left margin for text
					DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText

					; 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
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
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 $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] = $s
	Next
EndFunc

И мне всё равно хотелось бы адаптировать такую функцию в свой виртуальный ListView.
Вот он, с поиском по первому столбцу (индекс ноль) и инкрементальным фильтром.

Код:
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>

Opt("MustDeclareVars", 1)

Global $hGui, $hEdit, $idEditSearch, $hLV, $iItems = 5000, $aItems[$iItems][4], $aSearch[$iItems], $iSearch = 0, $sText

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()

	; 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")

	; Create ListView                                                Virtual listview
	Local $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", 130)
	_GUICtrlListView_AddColumn($hLV, "Sub1", 125)
	_GUICtrlListView_AddColumn($hLV, "Sub1", 130)
	_GUICtrlListView_AddColumn($hLV, "Sub2", 125)

	; Handle $WM_NOTIFY messages from ListView
	; Necessary to display the rows in a virtual ListView
	GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY_Search")

	; Show GUI
	GUISetState(@SW_SHOW)

	; Fill array
	For $i = 1 To 1000
		;$aItems[$i - 1][0] = $sText
		$aItems[$i - 1][1] = "AAA" & $i
		$aItems[$i - 1][2] = "BBB" & $i + 2
		$aItems[$i - 1][3] = "CCC" & $i + 3
	Next
	$iItems = $i
	FillArray( $aItems )

	; 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   ;==>Example

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

Func WM_NOTIFY_Search($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   ;==>WM_NOTIFY

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
	Next
EndFunc

И я попытался их соединить! Конечно это не заработало :(
При попытке добавлить стиль $LVS_OWNERDRAWFIXED, перестают отображаться элементы в ListView.
Вот что получилось:
Код:
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>
#include "DrawItem.au3"
#include "GuiListViewEx.au3"
#include <WinAPI.au3>

Opt("MustDeclareVars", 1)
Opt( "GUIResizeMode", $GUI_DOCKALL )

Global $hGui, $hEdit, $idEditSearch, $hListView, $iItems = 5000, $aItems[$iItems][4], $aSearch[$iItems], $iSearch = 0, $sText
Global Const $tagMSG = "hwnd hwnd;uint message;wparam wParam;lparam lParam;dword time;int X;int Y"
Global $idListView, $hListView, $fListViewHasFocus = 0
Global $idSearch, $hSearch, $idSearchAction, $sSearch = ""

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()

	; 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")

	; Create ListView                                                Virtual listview
	Local $idListView = GUICtrlCreateListView("", 10, 40, 600 - 20, 200 - 20, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER)
	;Local $idListView = GUICtrlCreateListView("", 10, 40, 600 - 20, 200 - 20, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA+$LVS_OWNERDRAWFIXED, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER)
	;->------>-------------------------------------------------------------------------------------------not work with $LVS_OWNERDRAWFIXED
	$hListView = GUICtrlGetHandle($idListView)
	_GUICtrlListView_AddColumn($hListView, "Item", 130)
	_GUICtrlListView_AddColumn($hListView, "Sub1", 125)
	_GUICtrlListView_AddColumn($hListView, "Sub1", 130)
	_GUICtrlListView_AddColumn($hListView, "Sub2", 125)

	; Handle $WM_NOTIFY messages from ListView
	; Necessary to display the rows in a virtual ListView
	GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY_Search")


	; Fill array
	For $i = 1 To 1000
		;$aItems[$i - 1][0] = $sText
		$aItems[$i - 1][1] = "AAA" & $i
		$aItems[$i - 1][2] = "BBB" & $i + 2
		$aItems[$i - 1][3] = "CCC" & $i + 3
	Next
	$iItems = $i
	FillArray( $aItems )

	; Set search array to include all items
	For $i = 0 To $iItems - 1
		$aSearch[$i] = $i
	Next
	$iSearch = $iItems

	; Display items
	GUICtrlSendMsg($idListView, $LVM_SETITEMCOUNT, $iSearch, 0)

	; 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 $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($idListView, $LVM_SETITEMCOUNT, $iSearch, 0)
				ConsoleWrite(StringFormat("%4d", $iSearch) & " rows matching """ & $sSearch & """" & @CRLF)

			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd

	GUIDelete()
EndFunc   ;==>Example

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

Func WM_NOTIFY_Search($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 $hListView
			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   ;==>WM_NOTIFY

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
	Next
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 )
	#forceref $hWnd, $iMsg, $wParam
	Local Static $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 )

	Local $tDrawItem = DllStructCreate( $tagDRAWITEM, $lParam )
	If DllStructGetData( $tDrawItem, "CtlType" ) <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG

	Switch DllStructGetData( $tDrawItem, "CtlID" )
		Case $idListView
			Switch DllStructGetData( $tDrawItem, "itemAction" )
				Case $ODA_DRAWENTIRE
					Local $iIndex = DllStructGetData( $tDrawItem, "itemID" ), $iState = DllStructGetData( $tDrawItem, "itemState" ), $hDC = DllStructGetData( $tDrawItem, "hDC" ), $sItemText = $aItems[$aSearch[$iIndex]]

					; Item rectangle
					Local $tRect = DllStructCreate( $tagRECT, DllStructGetPtr( $tDrawItem, "Left" ) )
					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 4 ) ; 4 pixel left margin for background

					; Item 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 item text
					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 2 ) ; Plus 2 pixel left margin for text
					DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText

					; 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
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
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

Наверно нужно подправить функцию WM_DRAWITEM, но сам я этого не осилю.
Я буду рад, если кто то будет готов поломать мозги и поправить то, что получилось.

Может кто то предложит своё решение, но с привязкой к моему примеру (двумерный виртуальный ListView).
Спасибо.

Для запуска оригинального примера потребуется три файла в #Include, прикреплены во вложении.
 

Вложения

ra4o

Скриптер
Сообщения
992
Репутация
183
Из того , что увидел - у Вас не отрабатывает функция "WM_DRAWITEM" потому , что внутри функции используется переменная "$idListView" , а она у Вас - локальная, уберите "Local" , при создании "ListView"
Далее , Вы используете Двумерный массив "$aItems" , следовательно допишите индекс при выборе текста подпункта (внутри функции "WM_DRAWITEM") в конце строки должно быть " $sItemText = $aItems[$aSearch[$iIndex]][0]" ну и далее допишите заполнение остальных столбцов.
Дальше уже не копался.
 
Автор
L

liond66

Новичок
Сообщения
52
Репутация
1
ra4o
Спасибо за Ваш ответ. Добавил стиль и внёс указанные изменения.
Поиск заработал с указаныым стилем, выделение жёлтым нет.

ra4o сказал(а):
... ну и далее допишите заполнение остальных столбцов.
Дальше уже не копался.
Мне сложно так понять. Копайте пожалуйста дальше :smile:
Я думаю, что это будет полезно и другим.
Спасибо.
 
Автор
L

liond66

Новичок
Сообщения
52
Репутация
1
Немного подправил код с учётом замечаний ra4o.
Перестала отображаться информация в колонках, кроме первой.
Как добавить? В $aSearch? Но это массив для поиска, нет? А я ищу по первой колонке.
По прежнему нет выделения жёлтым.
Помогите понять как это работает?

Код:
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>
#include "DrawItem.au3"
#include "GuiListViewEx.au3"
#include <WinAPI.au3>

Opt("MustDeclareVars", 1)
Opt( "GUIResizeMode", $GUI_DOCKALL )

Global $hGui, $hEdit, $idEditSearch, $hListView, $iItems = 5000, $aItems[$iItems][4], $aSearch[$iItems], $iSearch = 0, $sText
Global Const $tagMSG = "hwnd hwnd;uint message;wparam wParam;lparam lParam;dword time;int X;int Y"
Global $idListView, $hListView, $fListViewHasFocus = 0
Global $idSearch, $hSearch, $idSearchAction, $sSearch = ""

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()

	; 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")

	; Create ListView
	;$idListView = GUICtrlCreateListView("", 10, 40, 600 - 20, 200 - 20, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER)
	$idListView = GUICtrlCreateListView("", 10, 40, 600 - 20, 200 - 20, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA+$LVS_OWNERDRAWFIXED, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER)
	$hListView = GUICtrlGetHandle($idListView)
	_GUICtrlListView_AddColumn($hListView, "Item", 200)
	_GUICtrlListView_AddColumn($hListView, "Sub1", 100)
	_GUICtrlListView_AddColumn($hListView, "Sub1", 100)
	_GUICtrlListView_AddColumn($hListView, "Sub2", 100)

	; Handle $WM_NOTIFY messages from ListView
	; Necessary to display the rows in a virtual ListView
	GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY_Search")


	; Fill array
	FillArray( $aItems )
	For $i = 1 To 1000
		;$aItems[$i - 1][0] = $sText
		$aItems[$i - 1][1] = "AAA" & $i
		$aItems[$i - 1][2] = "BBB" & $i + 2
		$aItems[$i - 1][3] = "CCC" & $i + 3
	Next
	$iItems = $i


	; Set search array to include all items
	For $i = 0 To $iItems - 1
		$aSearch[$i] = $i
	Next
	$iSearch = $iItems

	; Display items
	GUICtrlSendMsg($idListView, $LVM_SETITEMCOUNT, $iSearch, 0)

	; 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 $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($idListView, $LVM_SETITEMCOUNT, $iSearch, 0)
				ConsoleWrite(StringFormat("%4d", $iSearch) & " rows matching """ & $sSearch & """" & @CRLF)

			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd

	GUIDelete()
EndFunc   ;==>Example

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

Func WM_NOTIFY_Search($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 $hListView
			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   ;==>WM_NOTIFY

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
	Next
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 )
	#forceref $hWnd, $iMsg, $wParam
	Local Static $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 )

	Local $tDrawItem = DllStructCreate( $tagDRAWITEM, $lParam )
	If DllStructGetData( $tDrawItem, "CtlType" ) <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG

	Switch DllStructGetData( $tDrawItem, "CtlID" )
		Case $idListView
			Switch DllStructGetData( $tDrawItem, "itemAction" )
				Case $ODA_DRAWENTIRE
					Local $iIndex = DllStructGetData( $tDrawItem, "itemID" )
					Local $iState = DllStructGetData( $tDrawItem, "itemState" )
					Local $hDC = DllStructGetData( $tDrawItem, "hDC" )
					Local $sItemText = $aItems[$aSearch[$iIndex]][0]

					; Item rectangle
					Local $tRect = DllStructCreate( $tagRECT, DllStructGetPtr( $tDrawItem, "Left" ) )
					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 4 ) ; 4 pixel left margin for background

					; Item 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 item text
					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 2 ) ; Plus 2 pixel left margin for text
					DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText

					; 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
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
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
 

ra4o

Скриптер
Сообщения
992
Репутация
183
По прежнему нет выделения жёлтым.
Код:
;Уберите в основном цикле "Local" в строке 
$sSearch = GUICtrlRead($idEdit)
;Измените в функции "WM_DRAWITEM" строку 
Local $sMatch = StringRegExp( $sItemText, $sSearch, 1 ), $extended = @extended, $iLen = StringLen( $sMatch[0] )
;на строку 
Local $sMatch = StringRegExp( $sItemText,'(?i)'& $sSearch, 1 ), $extended = @extended, $iLen = StringLen( $sMatch[0] ); (Поиск без учёта регистра символов)
 
Автор
L

liond66

Новичок
Сообщения
52
Репутация
1
Я в шоке!!! 4 знака, и функция заработала!!!
Высший пилотаж!!!
Я очень ценю Вашу помощь.
Осталось возвратить данные в столбцы 1,2,3.
Это уже легче (но не для меня :( ).
Прошу помощи.
Спасибо.
 
Автор
L

liond66

Новичок
Сообщения
52
Репутация
1
Повисло всё на пол дороги :(
Как вернуть отображение информации в столбиках 1,2,3?
Может это не так легко, как я себе представляю?
ra4o, Вы в теме, на Вас главная надежда.
А также приглашаю всех помочь с кодом.
Ещё раз выложу код после всех изменений.
Код:
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>
#include "DrawItem.au3"
#include "GuiListViewEx.au3"
#include <WinAPI.au3>

Opt("MustDeclareVars", 1)
Opt( "GUIResizeMode", $GUI_DOCKALL )

Global $hGui, $hEdit, $idEditSearch, $hListView, $iItems = 5000, $aItems[$iItems][4], $aSearch[$iItems], $iSearch = 0, $sText
Global Const $tagMSG = "hwnd hwnd;uint message;wparam wParam;lparam lParam;dword time;int X;int Y"
Global $idListView, $hListView, $fListViewHasFocus = 0, $idListView
Global $idSearch, $hSearch, $idSearchAction, $sSearch = ""

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()

	; 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")

	; Create ListView                                                Virtual listview
	;$idListView = GUICtrlCreateListView("", 10, 40, 600 - 20, 200 - 20, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER)
	$idListView = GUICtrlCreateListView("", 10, 40, 600 - 20, 200 - 20, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA+$LVS_OWNERDRAWFIXED, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER)

	$hListView = GUICtrlGetHandle($idListView)
	_GUICtrlListView_AddColumn($hListView, "Item", 200)
	_GUICtrlListView_AddColumn($hListView, "Sub1", 100)
	_GUICtrlListView_AddColumn($hListView, "Sub1", 100)
	_GUICtrlListView_AddColumn($hListView, "Sub2", 100)

	; Handle $WM_NOTIFY messages from ListView
	; Necessary to display the rows in a virtual ListView
	GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY_Search")


	; Fill array
	For $i = 1 To 1000
		;$aItems[$i - 1][0] = "KKK"; $sText
		$aItems[$i - 1][1] = "AAA" & $i
		$aItems[$i - 1][2] = "BBB" & $i + 2
		$aItems[$i - 1][3] = "CCC" & $i + 3
	Next
	$iItems = $i
	FillArray( $aItems )

	; Set search array to include all items
	For $i = 0 To $iItems - 1
		$aSearch[$i] = $i
	Next
	$iSearch = $iItems

	; Display items
	GUICtrlSendMsg($idListView, $LVM_SETITEMCOUNT, $iSearch, 0)

	; 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 $idEditSearch
				$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($idListView, $LVM_SETITEMCOUNT, $iSearch, 0)
				ConsoleWrite(StringFormat("%4d", $iSearch) & " rows matching """ & $sSearch & """" & @CRLF)

			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd

	GUIDelete()
EndFunc   ;==>Example

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

Func WM_NOTIFY_Search($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 $hListView
			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   ;==>WM_NOTIFY

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', 'v', 'b', 'N', 'M', '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
	Next
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 )
	#forceref $hWnd, $iMsg, $wParam
	Local Static $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 )

	Local $tDrawItem = DllStructCreate( $tagDRAWITEM, $lParam )
	If DllStructGetData( $tDrawItem, "CtlType" ) <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG

	Switch DllStructGetData( $tDrawItem, "CtlID" )
		Case $idListView
			Switch DllStructGetData( $tDrawItem, "itemAction" )
				Case $ODA_DRAWENTIRE
					Local $iIndex = DllStructGetData( $tDrawItem, "itemID" ), $iState = DllStructGetData( $tDrawItem, "itemState" ), $hDC = DllStructGetData( $tDrawItem, "hDC" ), $sItemText = $aItems[$aSearch[$iIndex]][0]

					; Item rectangle
					Local $tRect = DllStructCreate( $tagRECT, DllStructGetPtr( $tDrawItem, "Left" ) )
					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 4 ) ; 4 pixel left margin for background

					; Item 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 item text
					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 2 ) ; Plus 2 pixel left margin for text
					DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText

					; Matching substring?
					If $sSearch Then
						;Local $sMatch = StringRegExp( $sItemText, $sSearch, 1 ), $extended = @extended, $iLen = StringLen( $sMatch[0] )
						Local $sMatch = StringRegExp( $sItemText,'(?i)'& $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
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
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

Спасибо.
 

ra4o

Скриптер
Сообщения
992
Репутация
183
Пробуйте так :
Код:
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>
#include "DrawItem.au3"
#include "GuiListViewEx.au3"
#include <WinAPI.au3>

Opt("MustDeclareVars", 1)
Opt( "GUIResizeMode", $GUI_DOCKALL )

Global $hGui, $hEdit, $idEditSearch, $hListView, $iItems = 5000, $aItems[$iItems][4], $aSearch[$iItems], $iSearch = 0, $sText
Global Const $tagMSG = "hwnd hwnd;uint message;wparam wParam;lparam lParam;dword time;int X;int Y"
Global $idListView, $hListView, $fListViewHasFocus = 0, $idListView
Global $idSearch, $hSearch, $idSearchAction, $sSearch = ""

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()

    ; 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")

    ; Create ListView                                                Virtual listview
    ;$idListView = GUICtrlCreateListView("", 10, 40, 600 - 20, 200 - 20, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER)
    $idListView = GUICtrlCreateListView("", 10, 40, 600 - 20, 200 - 20, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA+$LVS_OWNERDRAWFIXED, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER)

    $hListView = GUICtrlGetHandle($idListView)
    _GUICtrlListView_AddColumn($hListView, "Item", 200)
    _GUICtrlListView_AddColumn($hListView, "Sub1", 100)
    _GUICtrlListView_AddColumn($hListView, "Sub1", 100)
    _GUICtrlListView_AddColumn($hListView, "Sub2", 100)

    ; Handle $WM_NOTIFY messages from ListView
    ; Necessary to display the rows in a virtual ListView
    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY_Search")


    ; Fill array
    For $i = 1 To 1000
        ;$aItems[$i - 1][0] = "KKK"; $sText
        $aItems[$i - 1][1] = "AAA" & $i
        $aItems[$i - 1][2] = "BBB" & $i + 2
        $aItems[$i - 1][3] = "CCC" & $i + 3
    Next
    $iItems = $i
    FillArray( $aItems )

    ; Set search array to include all items
    For $i = 0 To $iItems - 1
        $aSearch[$i] = $i
    Next
    $iSearch = $iItems

    ; Display items
    GUICtrlSendMsg($idListView, $LVM_SETITEMCOUNT, $iSearch, 0)

    ; 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 $idEditSearch
                $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($idListView, $LVM_SETITEMCOUNT, $iSearch, 0)
                ConsoleWrite(StringFormat("%4d", $iSearch) & " rows matching """ & $sSearch & """" & @CRLF)

            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd

    GUIDelete()
EndFunc   ;==>Example

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

Func WM_NOTIFY_Search($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 $hListView
            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   ;==>WM_NOTIFY

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', 'v', 'b', 'N', 'M', '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
    Next
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 )
    #forceref $hWnd, $iMsg, $wParam
    Local Static $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 )

    Local $tDrawItem = DllStructCreate( $tagDRAWITEM, $lParam )
    If DllStructGetData( $tDrawItem, "CtlType" ) <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG

    Switch DllStructGetData( $tDrawItem, "CtlID" )
        Case $idListView
            Switch DllStructGetData( $tDrawItem, "itemAction" )
                Case $ODA_DRAWENTIRE
                    Local $iIndex = DllStructGetData( $tDrawItem, "itemID" ), $iState = DllStructGetData( $tDrawItem, "itemState" ), $hDC = DllStructGetData( $tDrawItem, "hDC" ), _
					$sItemText = $aItems[$aSearch[$iIndex]][0] , $sItemText1 = $aItems[$aSearch[$iIndex]][1] ,$sItemText2 = $aItems[$aSearch[$iIndex]][2] , $sItemText3 = $aItems[$aSearch[$iIndex]][3]

                    ; Item rectangle
                    Local $tRect = DllStructCreate( $tagRECT, DllStructGetPtr( $tDrawItem, "Left" ) )
                    DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 4 ) ; 4 pixel left margin for background
					Local $tRect_0=$tRect

                    ; Item 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


                    Local $iWight_0=_GUICtrlListView_GetColumnWidth($idListView, 0)
                    Local $iWight_1=_GUICtrlListView_GetColumnWidth($idListView, 1)
                    Local $iWight_2=_GUICtrlListView_GetColumnWidth($idListView, 2)

                    ; Draw item text
					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + $iWight_0 + $iWight_1 + $iWight_2 )
                    DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText3, "int", StringLen( $sItemText3 ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText

					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) - $iWight_2 )
                    DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText2, "int", StringLen( $sItemText2 ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText

					DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) - $iWight_1)
                    DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText1, "int", StringLen( $sItemText1 ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText

                    DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) - $iWight_0 ) 
                    DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText


                    ; Matching substring?
                    If $sSearch Then
                        ;Local $sMatch = StringRegExp( $sItemText, $sSearch, 1 ), $extended = @extended, $iLen = StringLen( $sMatch[0] )
                        Local $sMatch = StringRegExp( $sItemText,'(?i)'& $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
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc
 
Автор
L

liond66

Новичок
Сообщения
52
Репутация
1
Попробовал. Работает на все 100%
Оказалось сложней, чем я предполагал.
Огромное спасибо!!!
:IL_AutoIt_1:

OffTopic:
Есть где нибудь обучалка по GUIRegisterMsg, или Wizard, или что нибудь заточенное под Autoit?
 

ra4o

Скриптер
Сообщения
992
Репутация
183
OffTopic:
Как таковой обучалки нет, открывайте примеры из справки для функций, смотрите, разбирайтесь.
 

RAMzor

Новичок
Сообщения
14
Репутация
0
Ребята! Действительно высший пилотаж!!! Снимаю шляпу!

Я попытался сменить поиск с 0й колонки на другую и получил крэш.
Как можно сделать поиск по другой колонке?
Было бы не плохо добавить выбор колонки для поиска в этом примере или просто тыкните носом что поменять
Сообщение автоматически объединено:

Я опять пошаманил немного...
Тут рабочий код с выбором колонки для поиска но БЕЗ маркировки (от liond66). Возможно кому-то пригодится.
Достаточно заменить [0] на другой номер (1, 2 или 3)
Код:
If StringInStr($aItems[$i][0], $sSearch) Then ; Normal search

Код:
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>
#include <GuiComboBox.au3>


Opt("MustDeclareVars", 1)

Global $hGui, $hEdit, $idEditSearch, $hLV, $iItems = 5000, $aItems[$iItems][4], $aSearch[$iItems], $iSearch = 0, $sText, $iSearchColumn = 0

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()

    Local $idColumnSel = GUICtrlCreateCombo("Search in 'Item' Column", 300, 10, 150, 20)
    GUICtrlSetData(-1, "Search in 'Sub1' Column|Search in 'Sub2' Column|Search in 'Sub3' Column", "Item")


    ; 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")

    ; Create ListView                                                Virtual listview
    Local $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", 200)
    _GUICtrlListView_AddColumn($hLV, "Sub1", 118)
    _GUICtrlListView_AddColumn($hLV, "Sub2", 118)
    _GUICtrlListView_AddColumn($hLV, "Sub3", 118)

    ; Handle $WM_NOTIFY messages from ListView
    ; Necessary to display the rows in a virtual ListView
    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY_Search")

    ; Show GUI
    GUISetState(@SW_SHOW)

    ; Fill array
    For $i = 1 To 1000
        ;$aItems[$i - 1][0] = $sText
        $aItems[$i - 1][1] = "AAA-" & Random(1000000, 9999999, 1) & $i
        $aItems[$i - 1][2] = "BBB-" & Random(1000000, 9999999, 1) & $i + 2
        $aItems[$i - 1][3] = "CCC-" & Random(1000000, 9999999, 1) & $i + 3
    Next
    $iItems = $i
    FillArray( $aItems )

    ; 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][$iSearchColumn], $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 $idColumnSel
                $iSearchColumn = _GUICtrlComboBox_GetCurSel($idColumnSel)
                GUICtrlSendToDummy($idEditSearch)

            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd

    GUIDelete()
EndFunc   ;==>Example




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




Func WM_NOTIFY_Search($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   ;==>WM_NOTIFY




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
    Next
EndFunc

:help:
В исправленном коде от ra4o (Пост #8) сделать подобное не получилось. Вылетает с ошибкой.

Прошу помощи
 
Последнее редактирование:
Верх