Тема: AHK: Поиск в ListView
Всем привет, есть вопрос.Как сделать поиск в ListView, в нем много строк, а мне нужно найти с определенным текстом, например строку School.
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Всем привет, есть вопрос.Как сделать поиск в ListView, в нем много строк, а мне нужно найти с определенным текстом, например строку School.
Щелчком по заголовку столбца упорядочить в алфавитном порядке. Либо, когда эл. упр. ListView является активным, нажать на клавиатуре клавишу с первой буквой искомого текста. Нужная строка выделится.
а мне нужно найти
Что именно вы понимаете под "найти"?
А у меня еще такой вопрос, не охота создавать еще одну тему.Как мне удалить пустые строки из ListView(нужно смотреть по первому столбцу)?
sergeiplugatyr пишет:а мне нужно найти
Что именно вы понимаете под "найти"?
Найти строку с конкретным названием.
Найти строку с конкретным названием.
В ListView нет строк, там ряды и колонки, у них есть соответствующие номера.
Ладно, мне нужно искать текст в 1 колонке.
И что получить в результате?
Мне нужно найти текст "School" в 1 колонке и получить в результате найденные ряд(ы).
Вот пример:
word := "School"
Gui, Add, ListView, r5 w200 hwndhListView, Place|Address
LV_Add("", "Home", "57a Gloucester Drive")
LV_Add("", "School", "14 Rue Dupuis")
LV_Add("", "Job", "343 Pinewood Crescent")
LV_Add("", "School", "1400 Boul. De Maissoneuve")
LV_ModifyCol()
Gui, Show
return
F10::
rows := ""
ControlGet, OutputVar, List, col1,, ahk_id %hListView%
Loop, parse, OutputVar, `n, `r
if InStr(A_LoopField, word)
rows .= "," . A_Index
MsgBox, % "Слово """ word """ " . (rows ? "находится в рядах " . RegExReplace(rows, "^\,") : "не найдено")
return
teadrinker, вот эту штуку хорошо б в Коллекцию.
Можно, только немного до ума довести. Вот есть такой вариант поиска и выделения найденного в ListView, годится и для своего, и для чужого процесса, на примере Диспетчера Задач:
SearchWord := "AutoHotkey"
SetBatchLines, -1
Process, Exist, taskmgr.exe
if !PID := ErrorLevel
Run, taskmgr.exe,,, PID
WinWait, ahk_pid %PID%
ControlGet, hLv, Hwnd,, SysListView321
if !IsObject(obj := ListView_SearchWord(SearchWord, hLv))
{
MsgBox, % "Слово " SearchWord " не найдено!"
return
}
for k, v in obj
{
ListView_SetSel(v.row, hLv)
MsgBox, 4100, % SearchWord, % "Найдено """ SearchWord """, ряд " v.row ", колонка " v.col "`nпродолжить?"
IfMsgBox, No
break
}
MsgBox, 4096, % SearchWord, Поиск завершён.
Return
ListView_SearchWord(word, hListView, col = "")
{
found := []
ControlGet, OutputVar, List, % col ? "col" . col : "",, ahk_id %hListView%
Loop, parse, OutputVar, `n, `r
{
row := A_Index
Loop, parse, A_LoopField, % A_Tab
if InStr(A_LoopField, word)
found.Insert({row: row, col: col := A_Index})
}
Return col ? found : ""
}
ListView_SetSel(row, hListView)
{
static LVIS_FOCUSED := 1, LVIS_SELECTED := 2, LVM_SETITEMSTATE := 0x102B, LVM_ENSUREVISIBLE := 0x1013
VarSetCapacity(LVITEM, 60)
NumPut(LVIS_FOCUSED | LVIS_SELECTED, LVITEM, 12)
NumPut(LVIS_FOCUSED | LVIS_SELECTED, LVITEM, 16)
WinGet, PID, PID, ahk_id %hListView%
; если ListView принадлежит другому процессу, структура LVITEM должна быть записана в его адресном пространстве
if DllCall("GetCurrentProcessId") != PID
&& !(b := IsObject(obj := WriteProcessMemory(&LVITEM, 60, PID)))
Return 0
SendMessage, LVM_ENSUREVISIBLE, row - 1,,, ahk_id %hListView%
SendMessage, LVM_SETITEMSTATE, row - 1, b ? obj.address : &LVITEM,, ahk_id %hListView%
b ? ReleaseProcessMemory(obj.handle, obj.address)
}
WriteProcessMemory(pStruct, size, PID)
{
static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20, MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x4
hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION | PROCESS_VM_WRITE, Int, 0, UInt, PID, Ptr)
address := DllCall("VirtualAllocEx", UInt, hProc, UInt, 0, UInt, size, UInt, MEM_COMMIT, UInt, PAGE_READWRITE, Ptr)
DllCall("WriteProcessMemory", Ptr, hProc, Ptr, address, Ptr, pStruct, UInt, size, UInt, 0)
Return address ? {address: address, handle: hProc} : DllCall("CloseHandle", Ptr, hProc)
}
ReleaseProcessMemory(hProc, address)
{
DllCall("VirtualFreeEx", Ptr, hProc, Ptr, address, UInt, 0, UInt, MEM_RELEASE := 0x8000)
DllCall("CloseHandle", Ptr, hProc)
}
Но проблема в том, что вся информация считывается единовременно, а в течение показа может меняться (добавляться или удаляться строки), и выделенные строки не будут соответствовать действительности.
Последний скрипт слишком "громоздкий", вот мой вариант:
Gui, Add, ListView, x1 y0 w628 h105 -0x4000000, Имя|Путь
Gui, Add, Edit, x3 y106 w115 h20 -Multi vEdit, % Edit := "*.*"
Gui, Add, Button, x121 y106 w100 h21 gSearch, Найти
Gui, Show, Center w632 h128, New GUI Window
Return
Search:
LV_Delete()
Gui, Submit, NoHide
SetWorkingDir, %A_Desktop%
Loop, % Edit, 1, 1
{
LV_Add("", A_LoopFileName, A_LoopFileLongPath)
}
LV_ModifyCol(1, "AutoHdr")
LV_ModifyCol(2, "AutoHdr")
Return
GuiClose:
ExitApp
Попробуйте Ваш вариант для поиска в Диспетчере Задач.
вот мой вариант
А где там поиск-то?
sergeiplugatyr пишет:вот мой вариант
А где там поиск-то?
Вводим в Edit то что нам нужно найти и жмем Найти.
Я, наверно, чего-то не понял. Запускаем скрипт, возникает окно с пустым ListView. Нажимаем на кнопку — в ListView заносятся файлы с десктопа. И как в их списке осуществлять поиск по словам?
Нужно сразу при запуске скрипта написать то что нужно найти например на рабочем столе(название какого либо файла).
Всем привет, есть вопрос.Как сделать поиск в ListView, в нем много строк, а мне нужно найти с определенным текстом, например строку School.
Где мы поиск-то осуществляем, на рабочем столе, или в ListView?
Поиск осуществляется в ListView.
У меня ничего не ищет. Загружаю файлы с рабочего стола. Один из них — desktop.ini. Как мне его найти в списке?
Я уже немного запутался если честно, но он походу ищет на рабочем столе.
Так скрипт-то кто писал?
Я писал.
Когда пишешь скрипт, желательно представлять что он делает, а то, не ровен час, можно и систему снести.
На AHK сносить систему глупо, для этого есть более мощные языки.
Так о глупом сносе и речь.
Поиск в ListView по словам с выделением и подсветкой:
#NoEnv
SetBatchLines, -1
#If Control := ListViewFocus()
^vk46:: ; Ctrl + F
hWnd := WinExist("A")
Gui, Search:Default
Gui, +Owner%hWnd% +AlwaysOnTop
Gui, Margin,, 10
Gui, Add, Text, x10 y10, Текст для поиска:
Gui, Add, Edit, x+5 yp-3 w150 h21 vEdit, % Edit
Gui, Add, Button, x+-125 y+10 w60 h21 gGo Default, Искать
Gui, Add, Button, x+5 yp wp hp gCancel, Отмена
Gui, Add, Radio, % "x15 yp+4 vRadio" (Radio != 0 ? " Checked" : ""), Вниз
Gui, Add, Radio, % "x+5 yp" (Radio = 0 ? " Checked" : ""), Вверх
WinGetPos, X, Y,,, A
Gui, Show, % "x" X + 100 " y" Y + 50, Поиск в ListView
return
Go:
GuiControlGet, Edit, Search:
if (Edit = "")
Goto, Cancel
ControlGet, hLv, hwnd,, % Control, ahk_id %hWnd%
oLv := ""
if !IsObject(oLv := New ListView(hLv, Edit))
{
MsgBox, 0x1030, Ошибка, Невозможно извлечь информацию из ListView!
return
}
GuiControlGet, Radio, Search:
Gui, Search:Destroy
ControlGet, Focus, List, Count Focused,, % "ahk_id" oLv.h
oFound := oLv.SearchWord(Focus, 1, Radio)
if (oFound.state = "not_found")
DllCall("MessageBox", Ptr, oLv.h, Str, "Текст """ Edit """ не найден!", Str, "Не найдено", UInt, 0x30)
else if (oFound.state = "found")
{
CurrentRow := oFound.row, CurrentCol := oFound.col
oLv.SetSel(CurrentRow), oLv.Highlight(CurrentRow, CurrentCol)
Hotkey, If, % ListViewFocus()
Hotkey, F3, Search, On
}
oFound := ""
return
Search:
(Radio && ++CurrentCol > oLv.CountCol) ? (CurrentCol := 1, ++CurrentRow)
(!Radio && --CurrentCol = 0) ? (CurrentCol := oLv.CountCol, --CurrentRow)
oFound := oLv.SearchWord(CurrentRow, CurrentCol, Radio)
if (oFound.state != "found")
Return
CurrentRow := oFound.row, CurrentCol := oFound.col
oLv.SetSel(CurrentRow), oLv.Highlight(CurrentRow, CurrentCol)
return
SearchGuiClose:
SearchGuiEscape:
Cancel:
Gui, Search:Destroy
return
Class ListView
{
__New(hListView, word)
{
ControlGet, CountCol, List, Count Col,, ahk_id %hListView%
if !CountCol
Return ""
WinGet, PID, PID, ahk_id %hListView%
this.h := hListView
this.pid := PID
this.comp := this.CompareCapacity(PID)
this.CountCol := CountCol
this.word := word
}
CompareCapacity(PID)
{
if !A_Is64bitOS
Return 1
if !hProc := DllCall("OpenProcess", UInt, PROCESS_QUERY_INFORMATION := 0x400, Int, 0, UInt, PID, Ptr)
Return
VarSetCapacity(b, 4)
DllCall("IsWow64Process", Ptr, hProc, Ptr, &b)
DllCall("CloseHandle", Ptr, hProc)
b := NumGet(b, "UInt")
Return ((A_PtrSize = 4 && b) || (A_PtrSize = 8 && !b)) ? 1 : ""
}
SearchWord(StartRow, StartCol, Direction)
{
if this.comp
Return this.SearchViaMessage(StartRow, StartCol, Direction)
else
Return this.SearchViaParsing(StartRow, StartCol, Direction)
}
SearchViaMessage(StartRow, StartCol, Direction)
{
static found
Direction ? (CurrentRow := StartRow-1
, CurrentCol := StartCol-1) : (CurrentRow := StartRow+1, CurrentCol := StartCol+1)
RemoteBuff := New RemoteBuffer(this.pid, (A_PtrSize = 4 ? 60 : 68) + 260*(A_IsUnicode ? 2 : 1))
Loop
{
ControlGet, RowsCount, List, Count,, % "ahk_id" this.h
(Direction && ++CurrentRow > RowsCount) ? CurrentRow := 1
(!Direction && --CurrentRow = 0) ? CurrentRow := RowsCount
Loop
{
if (Direction && ++CurrentCol > this.CountCol && !(CurrentCol := 0))
|| (!Direction && --CurrentCol = 0 && (CurrentCol := this.CountCol + 1))
break
Text := this.GetItemText(CurrentRow, CurrentCol, RemoteBuff)
if ((A_IsUnicode ? RegExMatch(Text, "i)(*UCP)\Q" this.word "\E") : InStr(Text, this.word)) && found := 1)
Return {state: "found", row: CurrentRow, col: CurrentCol}
if (board && CurrentRow = StartRow && CurrentCol = StartCol && !found)
Return {state: "not_found"}
((Direction && CurrentRow = RowsCount && CurrentCol = this.CountCol)
|| (!Direction && CurrentRow = 1 && CurrentCol = 1)) ? board := 1
(CurrentRow = StartRow && CurrentCol = StartCol) ? found := ""
}
}
}
SearchViaParsing(StartRow, StartCol, Direction)
{
static found, FirstItem
StartIndex := StartRow * this.CountCol + StartCol
ControlGet, Content, List,,, % "ahk_id" this.h
Loop, parse, Content, `n
{
CurrentRow := A_Index
Loop, parse, A_LoopField, % A_Tab
{
CurrentIndex := CurrentRow * this.CountCol + A_Index
if (!WaitingNear && (A_IsUnicode ? RegExMatch(A_LoopField, "i)(*UCP)\Q" this.word "\E") : InStr(A_LoopField, this.word)))
LastItem := CurrentIndex, !found ? (FirstItem := CurrentIndex, found := 1)
if (CurrentIndex = StartIndex)
{
if (!Direction && found && !(found := 0))
Return this.CreateFromIndex(LastItem)
Direction ? WaitingNear := 1
}
if (WaitingNear
&& (A_IsUnicode ? RegExMatch(A_LoopField, "i)(*UCP)\Q" this.word "\E") : InStr(A_LoopField, this.word))
&& !(found := 0))
Return this.CreateFromIndex(CurrentIndex)
}
}
if !found
Return {state: "not_found"}
else if !(found := 0)
Return this.CreateFromIndex(Direction ? FirstItem : LastItem)
}
CreateFromIndex(idx)
{
i := idx//this.CountCol, m := Mod(idx, this.CountCol)
Return {state: "found", row: m ? i : i - 1, col: m ? m : this.CountCol}
}
GetItemText(item, col, RemoteBuff)
{
static LVIF_TEXT := 1, LVM_GETITEM := (A_IsUnicode ? 0x104B : 0x1005), LVITEM_SIZE := A_PtrSize = 4 ? 60 : 68
VarSetCapacity(LVITEM, LVITEM_SIZE)
NumPut(LVIF_TEXT, LVITEM, "UInt")
NumPut(item-1, LVITEM, 4, "Int")
NumPut(col-1, LVITEM, 8, "Int")
NumPut(RemoteBuff.Ptr + LVITEM_SIZE, LVITEM, 16 + A_PtrSize, "Ptr")
NumPut(260, LVITEM, 16 + A_PtrSize*2, "Int")
RemoteBuff.Write(&LVITEM, LVITEM_SIZE)
SendMessage, LVM_GETITEM, 0, RemoteBuff.Ptr,, % "ahk_id" this.h
Return StrGet(RemoteBuff.Read(260*(A_IsUnicode ? 2 : 1), LVITEM_SIZE))
}
SetSel(row)
{
static LVIS_FOCUSED := 1, LVIS_SELECTED := 2, LVM_SETITEMSTATE := 0x102B, LVM_ENSUREVISIBLE := 0x1013
VarSetCapacity(LVITEM, LVITEM_SIZE := A_PtrSize = 4 ? 60 : 68)
NumPut(LVIS_FOCUSED | LVIS_SELECTED, LVITEM, 12)
NumPut(LVIS_FOCUSED | LVIS_SELECTED, LVITEM, 16)
RemoteBuff := New RemoteBuffer(this.pid, LVITEM_SIZE)
RemoteBuff.Write(&LVITEM, LVITEM_SIZE)
SendMessage, LVM_ENSUREVISIBLE, row - 1,,, % "ahk_id" this.h
SendMessage, LVM_SETITEMSTATE, row - 1, RemoteBuff.Ptr,, % "ahk_id" this.h
}
Highlight(row, col)
{
static counter
counter := 0, th := 3 ; толщина рамки
Gui, Highlighting:Default
Gui, Destroy
VarSetCapacity(Init, 4)
NumPut(col = 1 ? 1 : col - 1, Init, "UInt")
RemoteBuff := New RemoteBuffer(this.pid, 16)
RemoteBuff.Write(&Init, 4, 4)
SendMessage, LVM_GETSUBITEMRECT := 0x1038, row - 1, RemoteBuff.Ptr,, % "ahk_id" this.h
pAddr := RemoteBuff.Read(16)
l := NumGet(pAddr+0, "UInt"), t := NumGet(pAddr+0, 4, "UInt")
r := NumGet(pAddr+0, 8, "UInt"), b := NumGet(pAddr+0, 12, "UInt")
RemoteBuff := ""
(col = 1) ? (lprev := l, l := 0, r := lprev)
WinGetPos, X, Y,,, % "ahk_id" this.h
Gui, % "-Caption +ToolWindow +Owner" this.h " +hwndhGui"
Gui, Color, Red
Gui, Show, % "x" X + l + 1 " y" Y + t + 2 " w" (w := r - l) " h" (h := b - t) " Hide"
Prev_DHW := A_DetectHiddenWindows
DetectHiddenWindows, On
WinSet, Region, % "0-0 " w "-0 " w "-" h " 0-" h " 0-0 "
. th "-" th " " w - th "-" th " " w - th "-" h - th " " th "-" h - th " " th "-" th
, ahk_id %hGui%
DetectHiddenWindows, %Prev_DHW%
Gui, Show, NA
SetTimer, Flashing, 300
return
Flashing:
Gui, Highlighting:Default
if (++counter = 1)
Gui, Show, Hide
if (counter = 2)
Gui, Show, NA
if (counter = 3)
{
Gui, Destroy
SetTimer, Flashing, Off
}
return
}
}
Class RemoteBuffer
{
__New(PID, size)
{
static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20, PROCESS_VM_READ := 0x10
, MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x4
if !(this.hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, Int, 0, UInt, PID, Ptr))
Return ""
if !(this.ptr := DllCall("VirtualAllocEx", UInt, this.hProc, UInt, 0, UInt, size, UInt, MEM_COMMIT, UInt, PAGE_READWRITE, Ptr))
Return ""
this.size := size
}
__Delete()
{
DllCall("VirtualFreeEx", Ptr, this.hProc, Ptr, this.ptr, UInt, 0, UInt, MEM_RELEASE := 0x8000)
DllCall("CloseHandle", Ptr, this.hProc)
}
Read(size, offset = 0)
{
static LocalBuff
VarSetCapacity(LocalBuff, s := (size > (s := this.size - offset) ? s : size), 0)
DllCall("ReadProcessMemory", Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, &LocalBuff, UInt, s, UInt, 0)
VarSetCapacity(LocalBuff, -1)
Return &LocalBuff
}
Write(pLocalBuff, size, offset = 0)
{
return DllCall("WriteProcessMemory", Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, pLocalBuff, UInt, size, UInt, 0)
}
}
ListViewFocus()
{
ControlGetFocus, Control, A
if InStr(Control, "SysListView32") && !WinExist("Поиск в ListView")
return Control
}
Контрол ListView должен быть в фокусе. Ctrl+F, далее F3. В ANSI-версии кириллица регистрозависима.
Если не будет дополнений, добавлю в Коллекцию.
Спасибо teadrinker, работает.
Доброго времени суток, вопрос относится не совсем к поиску и всё же. У меня в ListView'e есть много строк и нужно каким то образом спуститься на самую нижнюю строку тем самым прокрутив весь список.
Send, ^{End}
Всё оказалось настолько просто, спасибо.
Только проблема в том что нужно сначала выделить строку и только потом это сработает, пробовал так:
LV_Modify(1, "Select")
Send, ^{End}
Но дело в том что строка выделяется серым цветом, а чтобы все работало нужно чтобы она была выделена синим цветом.
Gui, Add, ListView, vList w300 h200 r50, FirstCol|SecondCol
Loop 50
LV_Add("", "Field1", "Field2")
Gui, Show
return
F11::
GuiControl, Focus, List
SendInput, ^{End}
LV_Modify(LV_GetCount(), "Select")
return
В очередной раз спасибо:).
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться