Хочу лишь поделится своим небольшим опытом.
В библиотеке UDF GuiListView.au3 есть альтернативнае функци для создания таблиц:
_GUICtrlListView_Create, _GUICtrlListView_AddItem, _GUICtrlListView_AddSubItem
а так же функция _GUICtrlListView_FindInText для поиска пункта содержащего текст в любом месте таблицы.
Случайно заметил, что поиск с помощью нативных функций идет на много быстрее, а так же заметил, тот же эффект в создании таблиц
при помощи нативных GUICtrlCreateListView и GUICtrlCreateListViewItem.
Я решил сделать свою функцию для поиска, а с подачи xXx проверить работу во всх вариантах создания ListView.
После окончательной доработки, просто обалдел.
Скорость поиска во всех вариантах таблиц была намного выше а в "нативных" просто в разы превышает UDF.
В примере ниже этот-же тест со всеми тремя вариантами создания ListView и сравнения поиска в них.
Про скорость создания так же можно немного здесь поситать.
Передаваемые параметры идентичны параметрам из UDF (См. справку для _GUICtrlListView_FindInText )
Если кто-то уже имеет у себя в в скрипте #include <SendMessage.au3>, то имеет смысл использовать _SendMessage вместо __SendMessage
Маленькая напоминалка для создания "нативных" ListView
При заполнении пунктов текстом, в "нативных" ListView, нужно помнить о разделителе (по умолчанию "|")
В примере я намеренно засунул в текст "|" поскольку этот символ иногда тоже может попадаться в тексте.
Переработал пример предложенный xXx
Кстати ему отдельное спасибо за помощь, точнее подталкивание в нужное направление.
Более наглядный пример и альтернативная реализация того-же принципа от xXx
PS
В библиотеке GuiListView.au3 очень много нужных и незаменимых функций, но вместо некоторых стот пропробовать альтернативу.
В библиотеке UDF GuiListView.au3 есть альтернативнае функци для создания таблиц:
_GUICtrlListView_Create, _GUICtrlListView_AddItem, _GUICtrlListView_AddSubItem
а так же функция _GUICtrlListView_FindInText для поиска пункта содержащего текст в любом месте таблицы.
Случайно заметил, что поиск с помощью нативных функций идет на много быстрее, а так же заметил, тот же эффект в создании таблиц
при помощи нативных GUICtrlCreateListView и GUICtrlCreateListViewItem.
Я решил сделать свою функцию для поиска, а с подачи xXx проверить работу во всх вариантах создания ListView.
После окончательной доработки, просто обалдел.
Скорость поиска во всех вариантах таблиц была намного выше а в "нативных" просто в разы превышает UDF.
В примере ниже этот-же тест со всеми тремя вариантами создания ListView и сравнения поиска в них.
Про скорость создания так же можно немного здесь поситать.
Передаваемые параметры идентичны параметрам из UDF (См. справку для _GUICtrlListView_FindInText )
Если кто-то уже имеет у себя в в скрипте #include <SendMessage.au3>, то имеет смысл использовать _SendMessage вместо __SendMessage
Код:
Func _GUICtrlListView_FindInTextEx($hLtVw, $sText, $iStart = -1, $bWrapOK = True, $bReverse = False)
If $bReverse And $iStart = -1 Then Return -1
Local $iId, $iCount, $iColumns, $hWnd = $hLtVw, $iDm[2]
Local $tItem = DllStructCreate("struct;uint Mask;int Item;int SubItem;uint State;uint StateMask;ptr Text;int TextMax;int Image;lparam Param;" & _
"int Indent;int GroupID;uint Columns;ptr pColumns;ptr piColFmt;int iGroup;endstruct")
Local $pItem = DllStructGetPtr($tItem)
DllStructSetData($tItem, 'Mask', 0x00000004)
If Not IsHWnd($hLtVw) Then
$hWnd = GUICtrlGetHandle($hLtVw)
If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)
DllStructSetData($tItem, "Item", 0)
GUICtrlSendMsg($hLtVw, (0x1000+75), 0, $pItem)
$iId = DllStructGetData($tItem, 'Param')
If $iId > 0 And GUICtrlGetState($iId) > 0 Then
$iDm[0] = Opt("GUIDataSeparatorChar")
EndIf
$iCount = GUICtrlSendMsg($hLtVw, (0x1000+4), 0, 0)
$iColumns = HWnd(GUICtrlSendMsg($hLtVw, (0x1000 + 31), 0, 0))
Else
$iCount = _SendMessage($hLtVw, (0x1000+4))
$iColumns = HWnd(_SendMessage($hLtVw, (0x1000+31)))
EndIf
$iColumns = _SendMessage($iColumns, 0x1200)
Local $hWin = DllCall("user32.dll", "hwnd", "GetParent", "hwnd", $hWnd)
$hWin = $hWin[0]
If Not $hWin Then Return SetError(2, 0, 0)
Local $iI, $iJ, $aPrm[3] = [($iStart+1),($iCount-1),1]
If $bReverse Then Dim $aPrm[3] = [($iStart-1),0,-1]
If $iDm[0] <> "" Then $iDm[1] = Opt("GUIDataSeparatorChar", "⑀")
For $iI = $aPrm[0] To $aPrm[1] Step $aPrm[2]
If $iDm[1] <> "" Then
DllStructSetData($tItem, 'Item',$iI)
GUICtrlSendMsg($hLtVw, (0x1000+75), 0, $pItem)
If StringInStr(GUICtrlRead(DllStructGetData($tItem, 'Param')), $sText) Then
Opt("GUIDataSeparatorChar", $iDm[0])
Return $iI
EndIf
Else
For $iJ = 0 To $iColumns - 1
If StringInStr(ControlListView($hWin, "", $hLtVw, "GetText", $iI, $iJ), $sText) Then Return $iI
Next
EndIf
Next
If Not ((($iStart = -1) Or Not $bWrapOK) And Not $bReverse) Then
If $bReverse And $bWrapOK Then
Dim $aPrm[3] = [($iCount-1),($iStart+1),-1]
Else
$aPrm[0] = 0
$aPrm[1] = $iStart-1
EndIf
For $iI = $aPrm[0] To $aPrm[1] Step $aPrm[2]
If $iDm[1] <> "" Then
DllStructSetData($tItem, 'Item', $iI)
GUICtrlSendMsg($hLtVw, (0x1000+75), 0, $pItem)
If StringInStr(GUICtrlRead(DllStructGetData($tItem, 'Param')), $sText) Then
Opt("GUIDataSeparatorChar", $iDm[0])
Return $iI
EndIf
Else
For $iJ = 0 To $iColumns - 1
If StringInStr(ControlListView($hWin, "", $hLtVw, "GetText", $iI, $iJ), $sText) Then Return $iI
Next
EndIf
Next
EndIf
If $iDm[1] <> "" Then Opt("GUIDataSeparatorChar", $iDm[0])
Return -1
EndFunc
Маленькая напоминалка для создания "нативных" ListView
При заполнении пунктов текстом, в "нативных" ListView, нужно помнить о разделителе (по умолчанию "|")
В примере я намеренно засунул в текст "|" поскольку этот символ иногда тоже может попадаться в тексте.
Код:
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <Array.au3>
Global $sFindStr = 'Стр 4999 | Кол 9' ; Строка поиска
$hLVWin = GUICreate('ListView 5000 x 15. Сравнение создания и поиска строки', 1150, 300)
Local $Header, $aTime[3][5]
For $i = 1 To 25
$Header &= "Колонка " & $i &"|"
Next
$aTime[0][0] = "Создание ListView"
$aTime[0][1] = "0"
$aTime[1][0] = "Поиск с UDF"
$aTime[1][1] = 0
$aTime[2][0] = "Поиск с Ex"
$aTime[2][1] = 0
Local $hListView = _GUICtrlListView_Create($hLVWin, $Header, 2, 2, 1144, 268)
GUISetState()
GUISetCursor(15, 1)
Local $hTimer = TimerInit()
_GUICtrlListView_BeginUpdate($hListView)
For $i = 1 To 5000
_GUICtrlListView_AddItem($hListView, 'Стр ' & $i & ' | Кол 1')
For $j = 1 To 15
_GUICtrlListView_AddSubItem($hListView, ($i - 1), 'Стр ' & $i & ' | Кол ' & ($j + 1), $j)
Next
Next
_GUICtrlListView_EndUpdate($hListView)
$aTime[0][2] = Ceiling(TimerDiff($hTimer))
GUISetCursor(-1, 1)
MsgBox(262144, Default, "Время создание таблицы 5000x15 (Full UDF): "& $aTime[0][2] & @CRLF & @CRLF & _
"Далее последует сравнение поиска _GUICtrlListView...:"& @CRLF & @CRLF &"1. Функция из UDF -> _FindInText"& @CRLF & @CRLF &"2. Альтернатив. Ex -> _FindInTextEx")
GUISetCursor(15, 1)
$hTimer = TimerInit()
$iI = _GUICtrlListView_FindInText($hListView, $sFindStr)
$aTime[1][2] = Ceiling(TimerDiff($hTimer))
If $iI = -1 Then $aTime[1][1] += 1
GUISetCursor(-1, 1)
MsgBox(262144, 'Результат поиска c UDF', '_GUICtrlListView_FindInText()' & @LF & 'Индекс пункта: ' & $iI & @CRLF & 'Время поиска: '& $aTime[1][2])
GUISetCursor(15, 1)
$hTimer = TimerInit()
$iI = _GUICtrlListView_FindInTextEx($hListView, $sFindStr)
$aTime[2][2] = Ceiling(TimerDiff($hTimer))
If $iI = -1 Then $aTime[2][1] += 1
GUISetCursor(-1, 1)
MsgBox(262144, 'Результат поиска c Ex', '_GUICtrlListView_FindInTextEx()' & @LF & 'Индекс пункта: ' & $iI & @CRLF & 'Время поиска: '& $aTime[2][2])
GUICtrlDelete($hListView)
Local $hListView = GUICtrlCreateListView($Header, 2, 2, 1144, 268)
GUISetState()
GUISetCursor(15, 1)
Local $hTimer = TimerInit()
_GUICtrlListView_BeginUpdate($hListView)
For $i = 1 To 5000
_GUICtrlListView_AddItem($hListView, 'Стр ' & $i & ' | Кол 1')
For $j = 1 To 15
_GUICtrlListView_AddSubItem($hListView, ($i - 1), 'Стр ' & $i & ' | Кол ' & ($j + 1), $j)
Next
_GUICtrlListView_SetItemParam($hListView, $i, 1000+$i)
Next
_GUICtrlListView_EndUpdate($hListView)
$aTime[0][3] = Ceiling(TimerDiff($hTimer))
GUISetCursor(-1, 1)
MsgBox(262144, Default, "Время создание таблицы 5000x15 (Native + UDF): "& $aTime[0][3] & @CRLF & @CRLF & _
"Далее последует сравнение поиска _GUICtrlListView...:"& @CRLF & @CRLF &"1. Функция из UDF -> _FindInText"& @CRLF & @CRLF &"2. Альтернатив. Ex -> _FindInTextEx")
GUISetCursor(15, 1)
$hTimer = TimerInit()
$iI = _GUICtrlListView_FindInText($hListView, $sFindStr)
$aTime[1][3] = Ceiling(TimerDiff($hTimer))
If $iI = -1 Then $aTime[1][1] += 1
GUISetCursor(-1, 1)
MsgBox(262144, 'Результат поиска c UDF', '_GUICtrlListView_FindInText()' & @LF & 'Индекс пункта: ' & $iI & @CRLF & 'Время поиска: '& $aTime[1][3])
GUISetCursor(15, 1)
$hTimer = TimerInit()
$iI = _GUICtrlListView_FindInTextEx($hListView, $sFindStr)
$aTime[2][3] = Ceiling(TimerDiff($hTimer))
If $iI = -1 Then $aTime[2][1] += 1
GUISetCursor(-1, 1)
MsgBox(262144, 'Результат поиска c Ex', '_GUICtrlListView_FindInTextEx()' & @LF & 'Индекс пункта: ' & $iI & @CRLF & 'Время поиска: '& $aTime[2][3])
GUICtrlSendMsg($hListView, $LVM_DELETEALLITEMS, 0, 0)
Local $iDl = Opt("GUIDataSeparatorChar")
$hListView = GUICtrlCreateListView($Header, 2, 2, 1144, 268)
Opt("GUIDataSeparatorChar", "□")
GUISetCursor(15, 1)
$hTimer = TimerInit()
_GUICtrlListView_BeginUpdate($hListView)
For $i = 1 To 5000
$sListe = ""
For $j = 1 To 15
$sListe &= "Стр "& $i & " | Кол "& ($j + 1) &"□"
Next
GUICtrlCreateListViewItem($sListe, $hListView)
Next
_GUICtrlListView_EndUpdate($hListView)
$aTime[0][4] = Ceiling(TimerDiff($hTimer))
GUISetCursor(-1, 1)
Opt("GUIDataSeparatorChar", $iDl)
MsgBox(262144, Default, "Время создание таблицы 5000x15 (Full Native): "& $aTime[0][4] & @CRLF & @CRLF & _
"Далее последует сравнение поиска _GUICtrlListView...:"& @CRLF & @CRLF &"1. Функция из UDF -> _FindInText"& @CRLF & @CRLF &"2. Альтернатив. Ex -> _FindInTextEx")
GUISetCursor(15, 1)
$hTimer = TimerInit()
$iI = _GUICtrlListView_FindInText($hListView, $sFindStr)
$aTime[1][4] = Ceiling(TimerDiff($hTimer))
If $iI = -1 Then $aTime[1][1] += 1
MsgBox(262144, 'Результат поиска c UDF', '_GUICtrlListView_FindInText()' & @LF & 'Индекс пункта: ' & $iI & @CRLF & 'Время поиска: '& $aTime[1][4])
GUISetCursor(15, 1)
$hTimer = TimerInit()
$iI = _GUICtrlListView_FindInTextEx($hListView, $sFindStr, 120, False, False)
$aTime[2][4] = Ceiling(TimerDiff($hTimer))
If $iI = -1 Then $aTime[2][1] += 1
GUISetCursor(-1, 1)
MsgBox(262144, 'Результат поиска c Ex', '_GUICtrlListView_FindInTextEx()' & @LF & 'Индекс пункта: ' & $iI & @CRLF & 'Время поиска: '& $aTime[2][4])
_ArrayDisplay($aTime, "Результат", "", 0, Default, "Функция|Error|Full UDF|Native + UDF|Full Native")
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
GUIDelete()
Func _GUICtrlListView_FindInTextEx($hLtVw, $sText, $iStart = -1, $bWrapOK = True, $bReverse = False)
If $bReverse And $iStart = -1 Then Return -1
Local $iId, $iCount, $iColumns, $hWnd = $hLtVw, $iDm[2]
Local $tItem = DllStructCreate("struct;uint Mask;int Item;int SubItem;uint State;uint StateMask;ptr Text;int TextMax;int Image;lparam Param;" & _
"int Indent;int GroupID;uint Columns;ptr pColumns;ptr piColFmt;int iGroup;endstruct")
Local $pItem = DllStructGetPtr($tItem)
DllStructSetData($tItem, 'Mask', 0x00000004)
If Not IsHWnd($hLtVw) Then
$hWnd = GUICtrlGetHandle($hLtVw)
If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)
DllStructSetData($tItem, "Item", 0)
GUICtrlSendMsg($hLtVw, (0x1000+75), 0, $pItem)
$iId = DllStructGetData($tItem, 'Param')
If $iId > 0 And GUICtrlGetState($iId) > 0 Then
$iDm[0] = Opt("GUIDataSeparatorChar")
EndIf
$iCount = GUICtrlSendMsg($hLtVw, (0x1000+4), 0, 0)
$iColumns = HWnd(GUICtrlSendMsg($hLtVw, (0x1000 + 31), 0, 0))
Else
$iCount = _SendMessage($hLtVw, (0x1000+4))
$iColumns = HWnd(_SendMessage($hLtVw, (0x1000+31)))
EndIf
$iColumns = _SendMessage($iColumns, 0x1200)
Local $hWin = DllCall("user32.dll", "hwnd", "GetParent", "hwnd", $hWnd)
$hWin = $hWin[0]
If Not $hWin Then Return SetError(2, 0, 0)
Local $iI, $iJ, $aPrm[3] = [($iStart+1),($iCount-1),1]
If $bReverse Then Dim $aPrm[3] = [($iStart-1),0,-1]
If $iDm[0] <> "" Then $iDm[1] = Opt("GUIDataSeparatorChar", "⑀")
For $iI = $aPrm[0] To $aPrm[1] Step $aPrm[2]
If $iDm[1] <> "" Then
DllStructSetData($tItem, 'Item',$iI)
GUICtrlSendMsg($hLtVw, (0x1000+75), 0, $pItem)
If StringInStr(GUICtrlRead(DllStructGetData($tItem, 'Param')), $sText) Then
Opt("GUIDataSeparatorChar", $iDm[0])
Return $iI
EndIf
Else
For $iJ = 0 To $iColumns - 1
If StringInStr(ControlListView($hWin, "", $hLtVw, "GetText", $iI, $iJ), $sText) Then Return $iI
Next
EndIf
Next
If Not ((($iStart = -1) Or Not $bWrapOK) And Not $bReverse) Then
If $bReverse And $bWrapOK Then
Dim $aPrm[3] = [($iCount-1),($iStart+1),-1]
Else
$aPrm[0] = 0
$aPrm[1] = $iStart-1
EndIf
For $iI = $aPrm[0] To $aPrm[1] Step $aPrm[2]
If $iDm[1] <> "" Then
DllStructSetData($tItem, 'Item', $iI)
GUICtrlSendMsg($hLtVw, (0x1000+75), 0, $pItem)
If StringInStr(GUICtrlRead(DllStructGetData($tItem, 'Param')), $sText) Then
Opt("GUIDataSeparatorChar", $iDm[0])
Return $iI
EndIf
Else
For $iJ = 0 To $iColumns - 1
If StringInStr(ControlListView($hWin, "", $hLtVw, "GetText", $iI, $iJ), $sText) Then Return $iI
Next
EndIf
Next
EndIf
If $iDm[1] <> "" Then Opt("GUIDataSeparatorChar", $iDm[0])
Return -1
EndFunc
Кстати ему отдельное спасибо за помощь, точнее подталкивание в нужное направление.
Более наглядный пример и альтернативная реализация того-же принципа от xXx
PS
В библиотеке GuiListView.au3 очень много нужных и незаменимых функций, но вместо некоторых стот пропробовать альтернативу.
Последнее редактирование: