Здравствуйте.
Вот здесь https://www.autoitscript.com/forum/topic/179112-incremental-search-in-owner-drawn-listview/
я увидел довольно оригинальную функцию маркировки жёлтеньким найденых букв.
Взял оригинальный пример "2) Show matching rows only.au3". Но там проблема больших маленьких букв.
Вот код:
И мне всё равно хотелось бы адаптировать такую функцию в свой виртуальный ListView.
Вот он, с поиском по первому столбцу (индекс ноль) и инкрементальным фильтром.
И я попытался их соединить! Конечно это не заработало :(
При попытке добавлить стиль $LVS_OWNERDRAWFIXED, перестают отображаться элементы в ListView.
Вот что получилось:
Наверно нужно подправить функцию WM_DRAWITEM, но сам я этого не осилю.
Я буду рад, если кто то будет готов поломать мозги и поправить то, что получилось.
Может кто то предложит своё решение, но с привязкой к моему примеру (двумерный виртуальный ListView).
Спасибо.
Для запуска оригинального примера потребуется три файла в #Include, прикреплены во вложении.
Вот здесь 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, прикреплены во вложении.