Здравствуйте.
Есть два скрипта (прикреплены):
LV-Search.au3 включает поиск по первому столбику в ListView.
LV-Sort.au3 включает сортировку столбиков при нажатии на заголовок в ListView.
Я пытаюсь объединить их в один скрипт, но это не совсем работает.
Проблема скорее всего в строках 174, 176.
Пожалуйста помогите исправить.
Файл Cursor.au3 используется в скрипте LV-Sort.au3
Почистил немного код.
Исправил сортировку и для простоты оставил только по возростанию.
Но по прежнему работают поиск и сортировка по отдельности.
Или строка 180, или строка 182.
Теперь вопрос сводится к тому, можно ли объединить в функции WM_NOTIFY два правила с одинаковым Case $LVN_GETDISPINFOW ?
Есть два скрипта (прикреплены):
LV-Search.au3 включает поиск по первому столбику в ListView.
LV-Sort.au3 включает сортировку столбиков при нажатии на заголовок в ListView.
Я пытаюсь объединить их в один скрипт, но это не совсем работает.
Проблема скорее всего в строках 174, 176.
Пожалуйста помогите исправить.
Код:
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <GuiHeader.au3>
#include <MsgBoxConstants.au3>
#include "Cursor.au3"
Opt("MustDeclareVars", 1)
Global $hGui, $hEdit, $idEditSearch, $hLV, $iItems = 5000, $aItems[$iItems][3], $aSearch[$iItems], $iSearch = 0, $sText
Global Const $hKernel32Dll = DllOpen("kernel32.dll")
Global $iRows
; Sorting
Global $iSortCol = -1, $iSortDir = 0, $tIndex
Example()
Func Example()
; Create GUI
$hGui = GUICreate("Gui", 600, 230)
; Create Edit control
Local $idEdit = GUICtrlCreateEdit("", 10, 10, 300 - 20, 20, BitXOR($GUI_SS_DEFAULT_EDIT, $WS_HSCROLL, $WS_VSCROLL))
$hEdit = GUICtrlGetHandle($idEdit)
$idEditSearch = GUICtrlCreateDummy()
; Create ListView Virtual listview
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, "Sub2", 130)
Local $hHeader = _GUICtrlListView_GetHeader($hLV)
Local $iSortColPrev = -1, $iSortArrow
; Handle $WM_COMMAND messages from Edit control
; To be able to read the search string dynamically while it's typed in
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND_Search")
; Handle $WM_NOTIFY messages from ListView
; Necessary to display the rows in a virtual ListView
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
; Show GUI
GUISetState(@SW_SHOW)
;;;;;;;;;; added for sort ;;;;;;;;;;;;;
$iRows = 0
Local $tStrings, $pStrings
; Fill array
For $i = 1 To 1000
$aItems[$i - 1][1] = "AAA" & $i
$aItems[$i - 1][2] = "BBB" & $i + 2
Next
$iItems = $i
$iRows = FillArray($aItems)
$tStrings = DllStructCreate("uint[" & $iRows & "]")
$pStrings = DllStructGetPtr($tStrings)
SortStrings($aItems, $iRows, 0, $pStrings, $tStrings)
SortStrings($aItems, $iRows, 1, $pStrings, $tStrings)
SortStrings($aItems, $iRows, 2, $pStrings, $tStrings)
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
;;;;;;;;;;;;;;;;; end added for sort ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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 $idLV
$iSortCol = GUICtrlGetState($idLV)
$tIndex = $tStrings
If $iSortColPrev > -1 Then _
_GUICtrlHeader_SetItemFormat($hHeader, $iSortColPrev, $HDF_STRING)
If $iSortColPrev = $iSortCol Then
$iSortDir = 1 - $iSortDir
$iSortArrow = $iSortDir ? $HDF_SORTUP : $HDF_SORTDOWN
Else
$iSortDir = 1
$iSortColPrev = $iSortCol
$iSortArrow = $HDF_SORTUP
EndIf
_GUICtrlHeader_SetItemFormat($hHeader, $iSortCol, $HDF_STRING + $iSortArrow)
GUICtrlSendMsg($idLV, $LVM_SETSELECTEDCOLUMN, $iSortCol, 0)
DllCall("user32.dll", "int", "InvalidateRect", "hwnd", $hLV, "int", 0, "int", 1)
Case $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
WEnd
DllClose($hKernel32Dll)
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_Search
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
Local Static $tText = DllStructCreate("wchar[50]")
Local Static $pText = DllStructGetPtr($tText)
Local $tNMHDR, $hWndFrom, $iCode
$tNMHDR = DllStructCreate($tagNMHDR, $lParam)
$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
$iCode = DllStructGetData($tNMHDR, "Code")
Switch $hWndFrom
Case $hLV
Switch $iCode
Case $LVN_GETDISPINFOW
Local $tNMLVDISPINFO = DllStructCreate($tagNMLVDISPINFO, $lParam)
If BitAND(DllStructGetData($tNMLVDISPINFO, "Mask"), $LVIF_TEXT) Then
Local $sItem = $aItems[$aSearch[DllStructGetData($tNMLVDISPINFO, "Item")]][DllStructGetData($tNMLVDISPINFO, "SubItem")]
If $iSortCol = -1 Then
Local $sItem = $aItems[$aSearch[DllStructGetData($tNMLVDISPINFO, "Item")]][DllStructGetData($tNMLVDISPINFO, "SubItem")]
Else
If $iSortDir Then
Local $sItem = $aItems[$aSearch[DllStructGetData($tIndex, 1, DllStructGetData($tNMLVDISPINFO, "Item") + 1)]][DllStructGetData($tNMLVDISPINFO, "SubItem")]
Else
Local $sItem = $aItems[$aSearch[DllStructGetData($tIndex, 1, $iRows - DllStructGetData($tNMLVDISPINFO, "Item"))]][DllStructGetData($tNMLVDISPINFO, "SubItem")]
EndIf
EndIf
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 ;==>FillArray
Func SortStrings(ByRef $aItems, $iRows, $iCol, $pIndex, $tIndex)
Local $k, $s, $lo, $hi, $mi, $gt
HourglassCursor(True)
WinSetTitle($hGui, "", "Virtual ListViews. Sort strings: 0 rows")
For $i = 0 To $iRows / 10000 - 1
$k = $i * 10000
For $j = 0 To 9999
$s = $aItems[$k + $j][$iCol]
; Binary search
$lo = 0
$hi = $k + $j - 1
While $lo <= $hi
$mi = Int(($lo + $hi) / 2)
If StringCompare($s, $aItems[DllStructGetData($tIndex, 1, $mi + 1)][$iCol]) < 0 Then
$gt = 0
$hi = $mi - 1
Else
$gt = 1
$lo = $mi + 1
EndIf
WEnd
; Make space for the new value
DllCall($hKernel32Dll, "none", "RtlMoveMemory", "struct*", $pIndex + ($mi + 1) * 4, "struct*", $pIndex + $mi * 4, "ulong_ptr", ($k + $j - $mi) * 4)
; Insert new value
DllStructSetData($tIndex, 1, $k + $j, $mi + 1 + $gt)
Next
WinSetTitle($hGui, "", "Virtual ListViews. Sort strings: " & $k + 10000 & " rows")
Next
HourglassCursor(False)
WinSetTitle($hGui, "", "Virtual ListViews (sorted)")
EndFunc ;==>SortStrings
Func SortNumbers(ByRef $aItems, $iRows, $iCol, $pIndex, $tIndex)
Local $k, $n, $lo, $hi, $mi, $gt
HourglassCursor(True)
WinSetTitle($hGui, "", "Virtual ListViews. Sort numbers: 0 rows")
For $i = 0 To $iRows / 10000 - 1
$k = $i * 10000
For $j = 0 To 9999
$n = $aItems[$k + $j][$iCol]
; Binary search
$lo = 0
$hi = $k + $j - 1
While $lo <= $hi
$mi = Int(($lo + $hi) / 2)
If $n < $aItems[DllStructGetData($tIndex, 1, $mi + 1)][$iCol] Then
$gt = 0
$hi = $mi - 1
Else
$gt = 1
$lo = $mi + 1
EndIf
WEnd
; Make space for the new value
DllCall($hKernel32Dll, "none", "RtlMoveMemory", "struct*", $pIndex + ($mi + 1) * 4, "struct*", $pIndex + $mi * 4, "ulong_ptr", ($k + $j - $mi) * 4)
; Insert new value
DllStructSetData($tIndex, 1, $k + $j, $mi + 1 + $gt)
Next
WinSetTitle($hGui, "", "Virtual ListViews. Sort numbers: " & $k + 10000 & " rows")
Next
HourglassCursor(False)
WinSetTitle($hGui, "", "Virtual ListViews (sorted)")
EndFunc ;==>SortNumbers
Сообщение автоматически объединено:
Сообщение автоматически объединено:
Файл Cursor.au3 используется в скрипте LV-Sort.au3
Сообщение автоматически объединено:
Почистил немного код.
Исправил сортировку и для простоты оставил только по возростанию.
Но по прежнему работают поиск и сортировка по отдельности.
Или строка 180, или строка 182.
Теперь вопрос сводится к тому, можно ли объединить в функции WM_NOTIFY два правила с одинаковым Case $LVN_GETDISPINFOW ?
Код:
#include <GUIConstants.au3>
#include <GuiListView.au3>
Opt("MustDeclareVars", 1)
Global $hGui, $hEdit, $idEditSearch, $hLV, $iItems = 1000, $aItems[$iItems][3], $aSearch[$iItems], $iSearch = 0, $iRows = $iItems
Global Const $hKernel32Dll = DllOpen("kernel32.dll")
Global $iSortCol = -1, $tIndex
Example()
Func Example()
; Create GUI
$hGui = GUICreate("Gui", 600, 230)
; Create Edit control
Local $idEdit = GUICtrlCreateEdit("", 10, 10, 300 - 20, 20, BitXOR($GUI_SS_DEFAULT_EDIT, $WS_HSCROLL, $WS_VSCROLL))
$hEdit = GUICtrlGetHandle($idEdit)
$idEditSearch = GUICtrlCreateDummy()
; Create ListView Virtual listview
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", 220)
_GUICtrlListView_AddColumn($hLV, "Sub1", 125)
_GUICtrlListView_AddColumn($hLV, "Sub2", 130)
Local $hHeader = _GUICtrlListView_GetHeader($hLV)
Local $iSortColPrev = -1, $iSortArrow
; Handle $WM_COMMAND messages from Edit control
; To be able to read the search string dynamically while it's typed in
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND_Search")
; Handle $WM_NOTIFY messages from ListView
; Necessary to display the rows in a virtual ListView
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)
FillArray($aItems)
Local $tStrings1 = DllStructCreate("uint[" & $iRows & "]"), $pStrings1 = DllStructGetPtr($tStrings1)
Local $tStrings2 = DllStructCreate("uint[" & $iRows & "]"), $pStrings2 = DllStructGetPtr($tStrings2)
Local $tStrings3 = DllStructCreate("uint[" & $iRows & "]"), $pStrings3 = DllStructGetPtr($tStrings3)
SortStrings($aItems, $iRows, 0, $pStrings1, $tStrings1)
SortStrings($aItems, $iRows, 1, $pStrings2, $tStrings2)
SortStrings($aItems, $iRows, 2, $pStrings3, $tStrings3)
$tIndex = $tStrings1
; Set search array to include all items
For $i = 0 To $iItems - 1
$aSearch[$i] = $i
Next
$iSearch = $iItems
; Display items
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iSearch, 0)
While 1
Switch GUIGetMsg()
Case $idEditSearch
Local $sSearch = GUICtrlRead($idEdit)
If $sSearch = "" Then
; Empty search string, display all rows
For $i = 0 To $iItems - 1
$aSearch[$i] = $i
Next
$iSearch = $iItems
Else
; Find rows matching the search string
$iSearch = 0
For $i = 0 To $iItems - 1
If StringInStr($aItems[$i][0], $sSearch) Then ; Normal search
$aSearch[$iSearch] = $i
$iSearch += 1
EndIf
Next
EndIf
; Display items
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iSearch, 0)
Case $idLV
$iSortCol = GUICtrlGetState($idLV)
Switch $iSortCol
Case 0
$tIndex = $tStrings1
Case 1
$tIndex = $tStrings2
Case 2
$tIndex = $tStrings3
EndSwitch
_GUICtrlHeader_SetItemFormat($hHeader, $iSortColPrev, $HDF_STRING)
_GUICtrlHeader_SetItemFormat($hHeader, $iSortCol, $HDF_STRING + $HDF_SORTUP)
GUICtrlSendMsg($idLV, $LVM_SETSELECTEDCOLUMN, $iSortCol, 0)
DllCall("user32.dll", "int", "InvalidateRect", "hwnd", $hLV, "int", 0, "int", 1)
$iSortColPrev = $iSortCol
Case $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
WEnd
DllClose($hKernel32Dll)
GUIDelete()
EndFunc ;==>Example
Func FillArray(ByRef $aItems)
Local $aLetters[26] = ['A', 'B', 'C', 'D', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', _
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'], $s
For $i = 0 To $iItems - 1
$s = $aLetters[Random(0, 25, 1)]
For $j = 1 To Random(10, 30, 1)
$s &= $aLetters[Random(0, 25, 1)]
Next
$aItems[$i][0] = $s
$aItems[$i][1] = "AAA" & $i
$aItems[$i][2] = "BBB" & $i + 2
Next
EndFunc ;==>FillArray
Func SortStrings(ByRef $aItems, $iRows, $iCol, $pIndex, $tIndex)
Local $s, $lo, $hi, $mi
For $j = 0 To $iRows - 1
$s = $aItems[$j][$iCol]
; Binary search
$lo = 0
$hi = $j - 1
While $lo <= $hi
$mi = Int(($lo + $hi) / 2)
If StringCompare($s, $aItems[DllStructGetData($tIndex, 1, $mi + 1)][$iCol]) < 0 Then
$hi = $mi - 1
Else
$lo = $mi + 1
EndIf
WEnd
; Make space for the new value
If $j > $mi Then _
DllCall($hKernel32Dll, "none", "RtlMoveMemory", "struct*", $pIndex + ($mi + 1) * 4, "struct*", $pIndex + $mi * 4, "ulong_ptr", ($j - $mi) * 4)
; Insert new value
DllStructSetData($tIndex, 1, $j, $mi + 1 + ($lo = $mi + 1))
Next
EndFunc ;==>SortStrings
Func WM_COMMAND_Search($hWnd, $iMsg, $wParam, $lParam)
Local $hWndFrom = $lParam
Local $iCode = BitShift($wParam, 16) ; High word
Switch $hWndFrom
Case $hEdit
Switch $iCode
Case $EN_CHANGE
GUICtrlSendToDummy($idEditSearch)
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_COMMAND_Search
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
Local Static $tText = DllStructCreate("wchar[50]")
Local Static $pText = DllStructGetPtr($tText)
Local $tNMHDR, $hWndFrom, $iCode
$tNMHDR = DllStructCreate($tagNMHDR, $lParam)
$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
$iCode = DllStructGetData($tNMHDR, "Code")
Switch $hWndFrom
Case $hLV
Switch $iCode
Case $LVN_GETDISPINFOW
Local $tNMLVDISPINFO = DllStructCreate($tagNMLVDISPINFO, $lParam)
If BitAND(DllStructGetData($tNMLVDISPINFO, "Mask"), $LVIF_TEXT) Then
Local $iItem = DllStructGetData($tNMLVDISPINFO, "Item")
Local $iSubItem = DllStructGetData($tNMLVDISPINFO, "SubItem")
;Search
Local $sItem = $aItems[$aSearch[$iItem]][$iSubItem]
;Sort
Local $sItem = $aItems[DllStructGetData($tIndex, 1, $iItem + 1)][$iSubItem]
DllStructSetData($tText, 1, $sItem)
DllStructSetData($tNMLVDISPINFO, "Text", $pText)
DllStructSetData($tNMLVDISPINFO, "TextMax", StringLen($sItem))
EndIf
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY
Вложения
Последнее редактирование: