Тема: AHK: ListView
Привет форум. В кратце, сделал(пытаюсь сделать) что-то вроде функции, которая может создавать много окон с ListView и работать с каждым.
Всё работает в отличии LV_Add, когда вызываешь его в функции, то в список ListView не добавляется элемент. Хочу чтобы обратили внимание на подфункцию (sAction = "Gui_AddItem") и помогли разобраться в чем ошибка. Уже второй день голову ломаю.
Еще есть такой момент, когда в окне нажимаешь "загрузить папку", то LV_Add работает без проблем, причем все элементы добавляются в том окне, в котором нажимаешь кнопку.
Explorer("Gui_Create", "Admin")
Explorer("Gui_Create", "Guest")
Sleep 1000
Explorer("Gui_Show", "Guest")
Sleep 1000
Explorer("Gui_Show", "Admin")
Sleep 1000
Explorer("Gui_AddItem", "Admin", "C:\Users\Администратор\Desktop\INTRO.mp4", 27628721)
Explorer("Gui_AddItem", "Guest", "C:\Users\Администратор\Desktop.folder", 0);.folder - приписываю для удобности в конце названия папки(папка у меня тоже имеет расширение)
Explorer(sAction = -1, iValue = -1, iValue2 = -1, iValue3 = -1)
{
Static
Static iGui0 := 0, iIcons0 := 0
Static bIconsLoaded := 0
Static sSettings := "D:\Program Files\My\AHK\Sockets\RemoteControl\Settings.ini"
If(sAction = "Gui_Create")
{
If(iValue = -1 || Explorer("Gui_Get", iValue) != -1)
return -1
iGui0 += 1
iGui%iGui0%_name := iValue
iGui%iGui0%_show := 0
Gui, Gui%iGui0%:Add, Button, Default gButtonLoadFolder, Загрузить папку
Gui, Gui%iGui0%:Add, Button, x+20 gButtonClear, Очистить список
Gui, Gui%iGui0%:Add, ListView, xm r20 w700 viGui%iGui0%_MyListView gMyListView, Имя|Размер|Тип
LV_ModifyCol(2, "Integer")
; Создаем каталог ImageList, чтобы отобразить в элементе управления ListView несколько иконок.
ImageListID1 := IL_Create(10)
; Присоединяем к ListView каталог ImageLists:
LV_SetImageList(ImageListID1)
LV_SetImageList(ImageListID2)
Menu, MyContextMenu, Add, Открыть, ContextOpenFile
Menu, MyContextMenu, Add, Удалить, ContextProperties
Menu, MyContextMenu, Add, Переименовать, ContextClearRows
Menu, MyContextMenu, Add, Скачать, ContextClearRows
Menu, MyContextMenu, Default, Скачать
}
Else If(sAction = "Gui_Show")
{
If((i := Explorer("Gui_Get", iValue)) < 0)
return -1
Gui, Gui%i%: Show
iGui%iGui0%_show := 1
LV_Add(, 1, 2, 3, 4)
}
Else If(sAction = "Gui_Get")
{
If(iValue != -1)
{
Loop % iGui0
{
If(iGui%A_Index%_name = iValue)
return A_Index
}
}
return -1
}
Else If(sAction = "Icon_Save")
{
}
Else If(sAction = "Icon_Load")
{
If(bIconsLoaded)
return -1
}
Else If(sAction = "Gui_AddItem")
{
;iValue = Gui_name;iValue2 = File;iValue3 = FileSize
If((i := Explorer("Gui_Get", iValue)) < 0)
return -1
Gui, %i%: ListView, iGui%i%_MyListView
LV_Add(, "yo", "yo2", "yo3")
WriteDebug(1, "Gui:" iValue "| File:" iValue2)
; Убеждаемся, что переменная способна вместить самый длинный путь к файлу. Это необходимо,
; поскольку функция DllCall("Shell32\SHGetFileInfoA) должна иметь возможность сохранить в переменной новое имя файла.
VarSetCapacity(Filename, 260)
sfi_size = 352
VarSetCapacity(sfi, sfi_size)
; Увеличиваем быстродействие путем отключения на время загрузки обновления изображения.
;GuiControl, -Redraw, iGui%i%_MyListView
GuiControl, +Redraw, iGui%i%_MyListView
LV_Add("", A_LoopFileName, A_LoopFileDir, FileExt)
FileName := RegExReplace(iValue2, "\..*")
;Определяем это - Folder или File ?
FileExt := RegExReplace(iValue2, ".*\.")
FileSize := iValue3
WriteDebug(1, FileName "." FileExt)
Loop % iIcons0
{
if FileExt in EXE,ICO,ANI,CUR
{
ExtID := FileExt ; Особый ID как заполнитель.
; Помечаем IconNumber как не найденный, для того чтобы каждый тип файла мог иметь уникальную иконку.
IconNumber = 0
}
else ; Рассчитываем уникальный ID для нескольких других расширений/типов файлов.
{
ExtID = 0 ; Инициализируем переменную, чтобы оперировать расширениями более короткими, чем другие.
Loop 7 ; Ограничиваем расширение семью символами, чтобы оно уместилось в 64-битном значении.
{
StringMid, ExtChar, FileExt, A_Index, 1
if not ExtChar ; Больше никаких символов.
break
; Выводим уникальный ID, задавая для каждого символа особый двоичный разряд.
ExtID := ExtID | (Asc(ExtChar) << (8 * (A_Index - 1)))
}
; Проверяем, есть ли у этого расширения файла иконка в ImageLists. Если есть,
; можно избежать нескольких вызовов, а производительность загрузки существенно увеличится,
; особенно в папке, содержащей сотни файлов:
IconNumber := IconArray%ExtID%
}
; Создаем в элементе управления ListView новую строку и присваиваем ей номер иконки, заданной выше.
LV_Add("Icon" . IconNumber, FileName, A_LoopFileSizeKB, FileExt)
Return
}
LV_Add(, FileName, FileSize, FileExt)
}
Else If(sAction = "LoadIcons")
{
if not IconNumber ; Данное расширение еще не имеет иконки, поэтому загружаем ее.
{
; Получаем маленькую иконку высокого качества, ассоциированную с данным расширением файла.
if not DllCall("Shell32\SHGetFileInfoA", "str", FileName, "uint", 0
, "str", sfi, "uint", sfi_size, "uint", 0x101) ; 0x101 is SHGFI_ICON+SHGFI_SMALLICON
; Задаем переменной значение, выходящее за рамки допустимых значений,
; чтобы отобразить пустую иконку.
IconNumber = 9999999
else ; Загрузка иконки прошла успешно.
{
; Извлекаем из структуры элемент hIcon.
hIcon = 0
Loop 4
hIcon += *(&sfi + A_Index-1) << 8*(A_Index-1)
; Добавляем HICON непосредственно в каталоги маленьких и больших иконок.
; Используем ниже +1, чтобы преобразовать возвращенный индекс так,
; чтобы отсчет начинался не с 0, а с 1.
IconNumber := DllCall("ImageList_ReplaceIcon", "uint", ImageListID1, "int", -1, "uint", hIcon) + 1
DllCall("ImageList_ReplaceIcon", "uint", ImageListID2, "int", -1, "uint", hIcon)
; После того, как иконка скопирована в ImageLists, оригинал необходимо уничтожить:
DllCall("DestroyIcon", "uint", hIcon)
; Помещаем иконку в кэш, чтобы сэкономить память и улучшить производительность при загрузке.
IconArray%ExtID% := IconNumber
}
}
}
Else WriteDebug(1, "[Explorer] Bad function - " sAction)
}
Return
ButtonLoadFolder:
LV_Add(, 1, 2, 3, 4)
; Убеждаемся, что переменная способна вместить самый длинный путь к файлу. Это необходимо,
; поскольку функция ExtractAssociatedIconA() должна иметь возможность сохранить в переменной новое имя файла.
VarSetCapacity(Filename, 260)
sfi_size = 352
VarSetCapacity(sfi, sfi_size)
; Увеличиваем быстродействие путем отключения на время загрузки обновления изображения.
GuiControl, -Redraw, MyListView
FileName := A_LoopFileFullPath
; Создаем уникальный ID расширения, чтобы избежать символов,
; использование которых в именах переменных запрещено, например, тире.
; Этот метод уникального ID работает лучше, так как для поиска элемента
; в массиве не требуется цикл.
SplitPath, FileName,,, FileExt ; Получаем расширение файла.
if FileExt in EXE,ICO,ANI,CUR
{
ExtID := FileExt ; Особый ID как заполнитель.
; Помечаем IconNumber как не найденный, для того чтобы каждый тип файла мог иметь уникальную иконку.
IconNumber = 0
}
else ; Рассчитываем уникальный ID для нескольких других расширений/типов файлов.
{
ExtID = 0 ; Инициализируем переменную, чтобы оперировать расширениями более короткими, чем другие.
Loop 7 ; Ограничиваем расширение семью символами, чтобы оно уместилось в 64-битном значении.
{
StringMid, ExtChar, FileExt, A_Index, 1
if not ExtChar ; Больше никаких символов.
break
; Выводим уникальный ID, задавая для каждого символа особый двоичный разряд.
ExtID := ExtID | (Asc(ExtChar) << (8 * (A_Index - 1)))
}
; Проверяем, есть ли у этого расширения файла иконка в ImageLists. Если есть,
; можно избежать нескольких вызовов, а производительность загрузки существенно увеличится,
; особенно в папке, содержащей сотни файлов:
IconNumber := IconArray%ExtID%
}
if not IconNumber ; Данное расширение еще не имеет иконки, поэтому загружаем ее.
{
; Получаем маленькую иконку высокого качества, ассоциированную с данным расширением файла.
if not DllCall("Shell32\SHGetFileInfoA", "str", FileName, "uint", 0
, "str", sfi, "uint", sfi_size, "uint", 0x101) ; 0x101 is SHGFI_ICON+SHGFI_SMALLICON
; Задаем переменной значение, выходящее за рамки допустимых значений,
; чтобы отобразить пустую иконку.
IconNumber = 9999999
else ; Загрузка иконки прошла успешно.
{
; Извлекаем из структуры элемент hIcon.
hIcon = 0
Loop 4
hIcon += *(&sfi + A_Index-1) << 8*(A_Index-1)
; Добавляем HICON непосредственно в каталоги маленьких и больших иконок.
; Используем ниже +1, чтобы преобразовать возвращенный индекс так,
; чтобы отсчет начинался не с 0, а с 1.
IconNumber := DllCall("ImageList_ReplaceIcon", "uint", ImageListID1, "int", -1, "uint", hIcon) + 1
DllCall("ImageList_ReplaceIcon", "uint", ImageListID2, "int", -1, "uint", hIcon)
; После того, как иконка скопирована в ImageLists, оригинал необходимо уничтожить:
DllCall("DestroyIcon", "uint", hIcon)
; Помещаем иконку в кэш, чтобы сэкономить память и улучшить производительность при загрузке.
IconArray%ExtID% := IconNumber
}
}
LV_Add(, 1, 2, 3, 4)
GuiControl, +Redraw, MyListView ; Снова разрешаем обновление изображения (запрещенное выше).
LV_ModifyCol() ; Автоматически подгоняем размер столбцов под их содержимое.
LV_ModifyCol(3, 60) ; Немного расширяем столбец Size, чтобы был виден его заголовок.
return
ButtonClear:
LV_Delete() ; Очищаем ListView, но для простоты не трогаем кэш иконок.
return
MyListView:
if A_GuiEvent = DoubleClick ; Есть много других возможных значений, которые может проверить скрипт.
{
LV_GetText(FileName, A_EventInfo, 1) ; Получаем текст из первого поля.
LV_GetText(FileDir, A_EventInfo, 2) ; Получаем текст из второго поля.
Run %FileDir%\%FileName%,, UseErrorLevel
if ErrorLevel
MsgBox "%FileDir%\%FileName%" невозможно открыть.
}
return
GuiContextMenu: ; Запускается в ответ на щелчок правой клавишей мыши или на нажатие клавиши Apps.
; Отображаем меню только в ответ на щелчки в пределах элемента управления ListView.
if A_GuiControl <> MyListView
return
; Отображает меню согласно заданным координатам, A_GuiX и A_GuiY.
; Необходимость использования этих переменных объясняется тем,
; что меню появится в заданном месте даже при нажатии клавиши Apps:
Menu, MyContextMenu, Show, %A_GuiX%, %A_GuiY%
return
ContextOpenFile: ; Пользователь выбрал в контекстном меню пункт 'Открыть'.
ContextProperties: ; Пользователь выбрал в контекстном меню пункт 'Свойства'.
; Для простоты работаем только со строкой, находящейся в фокусе, а не со всеми выделенными строками.
FocusedRowNumber := LV_GetNext(0, "F") ; Находим строку, находящуюся в фокусе.
if not FocusedRowNumber ; Строк, находящихся в фокусе, нет.
return
LV_GetText(FileName, FocusedRowNumber, 1) ; Получаем текст из первого поля.
LV_GetText(FileDir, FocusedRowNumber, 2) ; Получаем текст из второго поля.
IfInString A_ThisMenuItem, Open ; Пользователь выбрал в контекстном меню пункт 'Открыть'.
Run %FileDir%\%FileName%,, UseErrorLevel
else ; Пользователь выбрал в контекстном меню пункт 'Свойства'.
Run Properties "%FileDir%\%FileName%",, UseErrorLevel
if ErrorLevel
MsgBox Невозможно выполнить указанное действие с "%FileDir%\%FileName%".
return
ContextClearRows: ; Пользователь выбрал в контекстном меню пункт 'Очистить'.
RowNumber = 0 ; Первая итерация начинает поиск с начала списка.
Loop
{
; Так как при удалении строки уменьшается RowNumber всех строк, расположенных ниже,
; вычитаем 1, чтобы поиск производился по тем же номерам строк, которые были найдены
; ранее (в случае, если выделяются соседние строки):
RowNumber := LV_GetNext(RowNumber - 1)
if not RowNumber ; Возвращен ноль, следовательно выделенных строк больше нет.
break
LV_Delete(RowNumber) ; Удаляем строку из элемента управления ListView.
}
return
GuiSize: ; Растягиваем или сжимаем элемент управления ListView в ответ на изменение размера окна.
if A_EventInfo = 1 ; Окно минимизировано. Никаких действий не требуется.
return
; В противном случае, размер окна изменен или увеличен до максимума.
; Изменяем размер элемента управления ListView в соответствии с изменением размера окна.
GuiControl, Move, MyListView, % "W" . (A_GuiWidth - 20) . " H" . (A_GuiHeight - 40)
return
GuiClose: ; После закрытия окна автоматически завершаем работу скрипта.
ExitApp
WriteDebug(iTime = 0, sText = "None string", iEnter = 1)
{
Static bStarted := 0
If(iTime = 0) {
sString := sText
} Else {
sString := "[" A_Hour ":" A_Min ":" A_Sec "] " sText
}
If (iEnter = 1) {
sString := sString "`n"
}
If(bStarted = 0)
FileAppend, ==========================================================================================================================================================================================`n, %A_ScriptDir%\explorer.log
FileAppend, %sString%, %A_ScriptDir%\explorer.log
bStarted := 1
}