1 (изменено: MandarinKa02, 2017-12-21 19:39:38)

Тема: 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
}

2 (изменено: serzh82saratov, 2017-07-31 17:31:36)

Re: AHK: ListView

Если в гуи один ListView.


Loop % 4
{
	Gui, %A_Index%:Add, ListView, vListView%A_Index% r15 w200, col 1|col 2|col 3  
	Gui, %A_Index%:Show, % "x" A_Index * 220, Gui %A_Index%
}
Sleep 400
Loop % 4
	Add(A_Index)
Return

Add(Gui) {
	Gui, %Gui%:Default
	LV_Add(, "yo1", "yo2", "yo3")
	Sleep 100
}

Если в гуи несколько ListView.


Loop % 10
{
	Gui, %A_Index%:Add, ListView, v1ListView%A_Index% r12 w120, col 1|col 2|col 3 
	Gui, %A_Index%:Add, ListView, v2ListView%A_Index% r12 w120, col 1|col 2|col 3 
	Gui, %A_Index%:Show, % "x" A_Index * 150, Gui %A_Index%
}
Sleep 400
Loop
	Loop % 10
		Add(A_Index, 1), Add(A_Index, 2)
Return

Add(Gui, List) {
	Gui, %Gui%:Default
	Gui, ListView, %List%ListView%Gui%
	LV_Add(, "yo1", "yo2", "yo3")
	Sleep 1
}

Справка.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

3

Re: AHK: ListView

Спасибо, добился чего хотел.