Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

Post your working scripts, libraries and tools
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Jul 2017, 19:14

See also:
Explorer column interaction (get/set: which appear, width, ascending/descending order) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=33129
jeeswg's Explorer tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=31755
How to navigate to next sibling folder from Windows Explorer? - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=40200
Last edited by jeeswg on 03 Dec 2017, 19:38, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Nov 2017, 00:36

Code: Select all

;functions for Desktop and Explorer folder windows:
;JEE_ExpWinGetFoc ;get focused file
;JEE_ExpWinGetSel ;get selected files (list)
;JEE_ExpWinSetFoc ;set focused file
;JEE_ExpWinSetSel ;set selected files
;JEE_ExpWinGetFileCount ;get file count (selected, total)
;JEE_ExpOpenContainingFolder ;select file(s) in folder (open new window)
;JEE_ExpOpenContainingFolder2 ;select file in folder (open new window)
;JEE_ExpOpenContainingFolderEx ;select file in folder (use existing window, else, open new window)
;JEE_ExpListOpenDirs ;get folders for open Explorer windows (list)
;JEE_ExpWinInvSel ;set selected files: invert selection
;JEE_ExpWinSelAll ;set selected files: select all
;JEE_ExpWinSelNone2 ;set selected files: select none
;JEE_ExpWinSelNone ;set selected files: select none
;JEE_ExpWinGetDir ;get Explorer window folder
;JEE_ExpWinSetDir ;set Explorer window folder (navigate) (or open file/url in new window)
;JEE_ExpWinNewFile ;create new file/folder (create file, focus file, start edit mode)
;JEE_ExpWinSelFirst ;set selected files: jump to first file/folder
;JEE_ExpWinGetText ;get text from visible rows (requires Acc library)

;==================================================

JEE_ExpWinGetFoc(hWnd:=0)
{
	local oItem, oWin, oWindows, vPath, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin in ComObjCreate("Shell.Application").Windows
			if (oWin.HWND = hWnd)
				break
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return

	vPath := oWin.Document.FocusedItem.path
	oWindows := oWin := oItem := ""
	return vPath
}

;==================================================

JEE_ExpWinGetSel(hWnd:=0, vSep:="`n")
{
	local oItem, oWin, oWindows, vCount, vOutput, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin in ComObjCreate("Shell.Application").Windows
			if (oWin.HWND = hWnd)
				break
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return

	vCount := oWin.Document.SelectedItems.Count
	vOutput := ""
	VarSetCapacity(vOutput, (260+StrLen(vSep))*vCount*2)
	for oItem in oWin.Document.SelectedItems
		if !(SubStr(oItem.path, 1, 3) = "::{")
			vOutput .= oItem.path vSep
	oWindows := oWin := oItem := ""
	return SubStr(vOutput, 1, -StrLen(vSep))
}

;==================================================

;vByPos allows you to use vName to specify a file by position (1-based index)
JEE_ExpWinSetFoc(hWnd, vName, vByPos:=0, vFlags:=0x1D)
{
	local oItems, oWin, oWindows, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin in ComObjCreate("Shell.Application").Windows
			if (oWin.HWND = hWnd)
				break
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return

	oItems := oWin.Document.Folder.Items
	;SVSI_FOCUSED = 0x10 ;SVSI_ENSUREVISIBLE := 0x8
	;SVSI_DESELECTOTHERS := 0x4 ;SVSI_EDIT := 0x3
	;SVSI_SELECT := 0x1 ;SVSI_DESELECT := 0x0
	if !vByPos
		oWin.Document.SelectItem(oItems.Item(vName), vFlags)
	else
		oWin.Document.SelectItem(oItems.Item(vName-1), vFlags)
	oWindows := oWin := oItems := ""
}

;==================================================

;the first file in the list can be given different flags to the other files
JEE_ExpWinSetSel(hWnd, vList, vSep:="`n", vFlagsF:=0x1D, vFlagsS:=0x1)
{
	local oItems, oWin, oWindows, vFlags, vName, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin in ComObjCreate("Shell.Application").Windows
			if (oWin.HWND = hWnd)
				break
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return

	oItems := oWin.Document.Folder.Items
	Loop, Parse, vList, % vSep
	{
		;SVSI_FOCUSED = 0x10 ;SVSI_ENSUREVISIBLE := 0x8
		;SVSI_DESELECTOTHERS := 0x4 ;SVSI_EDIT := 0x3
		;SVSI_SELECT := 0x1 ;SVSI_DESELECT := 0x0
		vFlags := (A_Index = 1) ? vFlagsF : vFlagsS
		if !InStr(A_LoopField, "\")
			oWin.Document.SelectItem(oItems.Item(A_LoopField), vFlags)
		else
		{
			SplitPath, A_LoopField, vName
			oWin.Document.SelectItem(oItems.Item(vName), vFlags)
		}
	}
	oWindows := oWin := oItems := ""
}

;==================================================

JEE_ExpWinGetFileCount(hWnd, ByRef vCountS, ByRef vCountT)
{
	local oWin, oWindows, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin in ComObjCreate("Shell.Application").Windows
			if (oWin.HWND = hWnd)
				break
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return

	vCountS := oWin.Document.SelectedItems.count
	vCountT := oWin.Document.Folder.Items.count
	oWindows := oWin := ""
}

;==================================================

JEE_ExpOpenContainingFolder(vList, vSep:="`n")
{
	local ArrayITEMIDLIST, DirITEMIDLIST, PathITEMIDLIST, vComSpec, vCount, vDir, vList2, vPath
	vPath := SubStr(vList, 1, InStr(vList vSep, vSep)-1)
	SplitPath, vPath,, vDir

	;this works but SHOpenFolderAndSelectItems is faster/smoother
	;if !InStr(vList, vSep)
	;{
	;	if FileExist(vPath)
	;	{
	;		vComSpec := A_ComSpec ? A_ComSpec : ComSpec
	;		Run, % vComSpec " /c explorer.exe /select, " Chr(34) vPath Chr(34),, Hide
	;	}
	;	else if InStr(FileExist(vDir), "D")
	;		Run, % vDir
	;	return
	;}

	vList2 := "", vCount := 0
	Loop, Parse, vList, % vSep
		if FileExist(A_LoopField)
			vList2 .= A_LoopField "`n", vCount += 1
	if !vCount
	{
		Run, % vDir
		return
	}
	VarSetCapacity(ArrayITEMIDLIST, vCount*A_PtrSize)
	Loop, Parse, vList, `n
	{
		DllCall("shell32\SHParseDisplayName", Str,A_LoopField, Ptr,0, PtrP,PathITEMIDLIST, UInt,0, Ptr,0)
		NumPut(PathITEMIDLIST, &ArrayITEMIDLIST, (A_Index-1)*A_PtrSize, "Ptr")
	}
	DllCall("ole32\CoInitializeEx", Ptr,0, UInt,0)
	DllCall("shell32\SHParseDisplayName", Str,vDir, Ptr,0, PtrP,DirITEMIDLIST, UInt,0, Ptr,0)
	DllCall("shell32\SHOpenFolderAndSelectItems", Ptr,DirITEMIDLIST, UInt,vCount, Ptr,&ArrayITEMIDLIST, UInt,0)
	DllCall("ole32\CoTaskMemFree", Ptr,DirITEMIDLIST)
	Loop, % vCount
		DllCall("ole32\CoTaskMemFree", Ptr,NumGet(&ArrayITEMIDLIST, (A_Index-1)*A_PtrSize, "Ptr"))
	DllCall("ole32\CoUninitialize")
}
return

;==================================================

JEE_ExpOpenContainingFolder2(vPath)
{
	local vComSpec
	if FileExist(vPath)
	{
		vComSpec := A_ComSpec ? A_ComSpec : ComSpec
		Run, % vComSpec " /c explorer.exe /select, " Chr(34) vPath Chr(34),, Hide
	}
	else if InStr(FileExist(vDir), "D")
		Run, % vDir
}

;==================================================

JEE_ExpOpenContainingFolderEx(vPath)
{
	local oItems, oWin, vComSpec, vDir, vName
	SplitPath, vPath, vName, vDir
	if !FileExist(vPath)
	{
		if FileExist(vDir)
			Run, % vDir
		return
	}
	for oWin in ComObjCreate("Shell.Application").Windows
		if (oWin.Name = "Windows Explorer")
		&& (vDir = oWin.Document.Folder.Self.Path)
		{
			WinActivate, % "ahk_id " oWin.HWND
			;SVSI_FOCUSED = 0x10 ;SVSI_ENSUREVISIBLE := 0x8
			;SVSI_DESELECTOTHERS := 0x4 ;SVSI_EDIT := 0x3
			;SVSI_SELECT := 0x1 ;SVSI_DESELECT := 0x0
			oItems := oWin.Document.Folder.Items
			oWin.Document.SelectItem(oItems.Item(vName), 0x1D)
			oWin := oItems := ""
			return
		}
	oWin := ""
	vComSpec := A_ComSpec ? A_ComSpec : ComSpec
	Run, % vComSpec " /c explorer.exe /select, " Chr(34) vPath Chr(34),, Hide
}

;==================================================

JEE_ExpListOpenDirs(vSep:="`n")
{
	local oWin, vOutput
	for oWin in ComObjCreate("Shell.Application").Windows
		if (oWin.Name = "Windows Explorer")
			vOutput .= oWin.Document.Folder.Self.Path vSep
	oWin := ""
	return SubStr(vOutput, 1, -StrLen(vSep))
}

;==================================================

JEE_ExpWinInvSel(hWnd:=0)
{
	(!hWnd) && hWnd := WinExist("A")
	SendMessage, 0x111, 28706, 0, SHELLDLL_DefView1, % "ahk_id " hWnd ;WM_COMMAND := 0x111 ;(invert selection)
}

;==================================================

JEE_ExpWinSelAll(hWnd:=0)
{
	(!hWnd) && hWnd := WinExist("A")
	SendMessage, 0x111, 28705, 0, SHELLDLL_DefView1, % "ahk_id " hWnd ;WM_COMMAND := 0x111 ;(select all)
}

;==================================================

JEE_ExpWinSelNone2(hWnd:=0)
{
	(!hWnd) && hWnd := WinExist("A")
	SendMessage, 0x111, 28705, 0, SHELLDLL_DefView1, % "ahk_id " hWnd ;select all
	SendMessage, 0x111, 28706, 0, SHELLDLL_DefView1, % "ahk_id " hWnd ;invert selection
}

;==================================================

JEE_ExpWinSelNone(hWnd:=0)
{
	local oItem, oItems, oWin, oWindows, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin in ComObjCreate("Shell.Application").Windows
			if (oWin.HWND = hWnd)
				break
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return

	;SVSI_FOCUSED = 0x10 ;SVSI_ENSUREVISIBLE := 0x8
	;SVSI_DESELECTOTHERS := 0x4 ;SVSI_EDIT := 0x3
	;SVSI_SELECT := 0x1 ;SVSI_DESELECT := 0x0
	oItems := oWin.Document.Folder.Items
	oWin.Document.SelectItem(oItems.Item(0), 0x14)
	oWindows := oWin := oItems := ""
}

;==================================================

JEE_ExpWinGetDir(hWnd:=0)
{
	local oWin, oWindows, vDir, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin in ComObjCreate("Shell.Application").Windows
			if (oWin.HWND = hWnd)
				break
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return
	vDir := oWin.Document.Folder.Self.Path
	oWindows := oWin := ""
	return vDir
}

;==================================================

;sets dir (or opens file/url in new window)
JEE_ExpWinSetDir(hWnd, vDir)
{
	local oWin, vPIDL, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if !(vWinClass = "CabinetWClass") && !(vWinClass = "ExploreWClass")
		return
	for oWin in ComObjCreate("Shell.Application").Windows
		if (oWin.HWND = hWnd)
		{
			if !InStr(vDir, "#") || InStr(vDir, "://") ;folders that don't contain #, and urls
				oWin.Navigate(vDir)
			else ;folders that contain #
			{
				DllCall("shell32\SHParseDisplayName", WStr,vDir, Ptr,0, PtrP,vPIDL, UInt,0, Ptr,0)
				VarSetCapacity(SAFEARRAY, A_PtrSize=8?32:24, 0)
				NumPut(1, &SAFEARRAY, 0, "UShort") ;cDims
				NumPut(1, &SAFEARRAY, 4, "UInt") ;cbElements
				NumPut(vPIDL, &SAFEARRAY, A_PtrSize=8?16:12, "Ptr") ;pvData
				NumPut(DllCall("shell32\ILGetSize", Ptr,vPIDL, UInt), &SAFEARRAY, A_PtrSize=8?24:16, "Int") ;rgsabound[1]
				oWin.Navigate2(ComObject(0x2011, &SAFEARRAY), 0)
				DllCall("shell32\ILFree", Ptr,vPIDL)
			}
			break
		}
	oWin := ""
}

;==================================================

;e.g. JEE_ExpWinNewFile(hWnd, "New Text Document", "txt")
;e.g. JEE_ExpWinNewFile(hWnd, "New Folder", "", "d")
;e.g. JEE_ExpWinNewFile(hWnd, "New AutoHotkey Script", "ahk", "mc", "C:\Windows\ShellNew\Template.ahk")

;vOpt: d (dir), m/c (set modified/created dates to now, i.e. for copied template files)
JEE_ExpWinNewFile(hWnd, vNameNoExt, vExt, vOpt:="", vPathTemplate:="")
{
	local oItems, oWin, oWindows, vDir, vFlags, vName, vPath, vSfx, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin in ComObjCreate("Shell.Application").Windows
			if (oWin.HWND = hWnd)
				break
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return

	vDir := oWin.Document.Folder.Self.Path
	if !InStr(FileExist(vDir), "D")
	{
		oWindows := oWin := ""
		return
	}

	;note: Explorer creates files e.g. 'File, File (2), File (3)', but with no 'File (1)'
	if !(vExt = "")
		vExt := "." vExt
	Loop
	{
		vSfx := (A_Index=1) ? "" : " (" A_Index ")"
		vName := vNameNoExt vSfx vExt
		vPath := vDir "\" vName
		if !FileExist(vPath)
			break
	}
	if InStr(vOpt, "d")
		FileCreateDir, % vPath
	else if (vPathTemplate = "")
		FileAppend,, % vPath
	else
		FileCopy, % vPathTemplate, % vPath

	if InStr(vOpt, "m")
		FileSetTime,, % vPath, M
	if InStr(vOpt, "c")
		FileSetTime,, % vPath, C

	;SVSI_FOCUSED = 0x10 ;SVSI_ENSUREVISIBLE := 0x8
	;SVSI_DESELECTOTHERS := 0x4 ;SVSI_EDIT := 0x3
	;SVSI_SELECT := 0x1 ;SVSI_DESELECT := 0x0
	vFlags := WinActive("ahk_id " hWnd) ? 0x1F : 0x1D
	Loop, 30
	{
		oItems := oWin.Document.Folder.Items
		if !(oItems.Item(vName).path = "")
		{
			oWin.Document.SelectItem(oItems.Item(vName), vFlags)
			break
		}
		Sleep 100
	}
	oWindows := oWin := oItems := ""
}

;==================================================

;1=jump to first file, 0=jump to first dir, -1=toggle
;toggle jump to first file/folder
;note: slow on folders with lots of files/folders
JEE_ExpWinSelFirst(hWnd:=0, vOpt:=-1)
{
	local oItem, oItems, oWin, oWindows, vIsDir, vWinClass
	DetectHiddenWindows, On
	(!hWnd) && hWnd := WinExist("A")
	WinGetClass, vWinClass, % "ahk_id " hWnd
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin in ComObjCreate("Shell.Application").Windows
			if (oWin.HWND = hWnd)
				break
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return

	if (vOpt = -1)
		vIsDir := -!oWin.Document.FocusedItem.IsFolder ;IsFolder returns -1=true, 0=false
	else if (vOpt = 1)
		vIsDir := 0
	else if (vOpt = 0)
		vIsDir := -1
	for oItem in oWin.Document.Folder.Items
		if (vIsDir = oItem.IsFolder)
		{
			;SVSI_FOCUSED = 0x10 ;SVSI_ENSUREVISIBLE := 0x8
			;SVSI_DESELECTOTHERS := 0x4 ;SVSI_EDIT := 0x3
			;SVSI_SELECT := 0x1 ;SVSI_DESELECT := 0x0
			oWin.Document.SelectItem(oItem, 0x1D)
			break
		}
	oWindows := oWin := oItems := ""
}

;==================================================

Code: Select all

;[Acc functions]
;Acc library (MSAA) and AccViewer download links - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=26201

;==================================================

JEE_ExpWinGetText(hWnd, vSep:="`n")
{
	ControlGet, hCtl, Hwnd,, DirectUIHWND3, % "ahk_id " hWnd
	oAcc := Acc_Get("Object", "4", 0, "ahk_id " hCtl)
	for _, oChild in Acc_Children(oAcc)
	{
		if !(oChild.accRole(0) = 0x22) ;ROLE_SYSTEM_LISTITEM := 0x22
			continue
		for _, oChild2 in Acc_Children(oChild)
			if (oChild2.accRole(0) = 0x2A) ;ROLE_SYSTEM_TEXT := 0x2A
			{
				try vOutput .= oChild2.accValue(0) "`t"
				catch
					vOutput .= "`t"
			}
		vOutput := SubStr(vOutput, 1, -1) vSep
	}
	oAcc := oChild := oChild2 := ""
	return SubStr(vOutput, 1, -StrLen(vSep))
}

;==================================================
[EDIT:] I will update the functions to allow returning an array, like this new version of JEE_ExpWinGetSel:

Code: Select all

;requires:
;commands as functions (AHK v2 functions for AHK v1) - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=37&t=29689

JEE_ExpWinGetSel(hWnd:=0, vSep:="")
{
	local oItem, oOutput, oWin, oWindows, vCount, vOutput, vWinClass
	DetectHiddenWindows("On")
	(!hWnd) && hWnd := WinExist("A")
	vWinClass := WinGetClass("ahk_id " hWnd)
	if (vWinClass = "CabinetWClass") || (vWinClass = "ExploreWClass")
	{
		for oWin2 in ComObjCreate("Shell.Application").Windows
			if (oWin2.HWND = hWnd)
			{
				oWin := oWin2
				break
			}
	}
	else if (vWinClass = "Progman") || (vWinClass = "WorkerW")
	{
		oWindows := ComObjCreate("Shell.Application").Windows
		VarSetCapacity(hWnd, 4, 0)
		;SWC_DESKTOP := 0x8 ;VT_BYREF := 0x4000 ;VT_I4 := 0x3 ;SWFO_NEEDDISPATCH := 0x1
		oWin := oWindows.FindWindowSW(0, "", 8, ComObject(0x4003, &hWnd), 1)
	}
	else
		return

	vCount := oWin.Document.SelectedItems.Count
	if (vSep = "")
	{
		oOutput := []
		for oItem in oWin.Document.SelectedItems
			if !(SubStr(oItem.path, 1, 3) = "::{")
				oOutput.Push(oItem.path)
		oWindows := oWin := oWin2 := oItem := ""
		return oOutput
	}
	else
	{
		vOutput := ""
		VarSetCapacity(vOutput, (260+StrLen(vSep))*vCount*2)
		for oItem in oWin.Document.SelectedItems
			if !(SubStr(oItem.path, 1, 3) = "::{")
				vOutput .= oItem.path vSep
		oWindows := oWin := oWin2 := oItem := ""
		return SubStr(vOutput, 1, -StrLen(vSep))
	}
}
Last edited by jeeswg on 01 Aug 2018, 12:12, edited 2 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Nov 2017, 13:52

Very nice jeeswg, I tested a few, seems good, thanks for sharing. :thumbup:
Cheer!
FYI
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Nov 2017, 15:17

'Things that Helgef told me': assume global available but no assume local available/force an expression + can be an expression with % %var%/numeric keys in AHK v2/objects + for loop in AHK v2. Any other AHK v2 gotchas?

This is very important information, but clearly, I do one of two for loops to get the object, based on whether it's an Explorer window or Desktop, and then I go on to do the code proper. How can I do this, if it all, in AHK v2, without duplicating the code, by having it appear twice, once inside each for loop? Thanks.

[EDIT:] OK, in this particular case getting the Desktop object doesn't require a for loop. But the point remains e.g. what if I wanted to try a for loop in one Explorer window, and then another for loop in another Explorer window, get the object in one or other, and then go on to do the code proper. Anyhow, if I place the Desktop line into the for loop somehow, it will look ugly and make the code less clear.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Nov 2017, 15:29

For two-way compatabillity, I'd do,

Code: Select all

for oWinKey in ComObjCreate("Shell.Application").Windows
	if (oWinKey.HWND = hWnd) {
		oWin := oWinKey
		break
	}
if that is what you are asking?

Cheers
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Nov 2017, 15:37

- So it's as simple as creating a new object (object reference) within the for loop, and that way it can survive outside the for loop? I wasn't sure if that would work or not.
- I'll take a look at AHK v2 changes again, I get up-to-date every so often, and then subtle changes are made. I'll take a close look at objects, which I had assumed would stay mostly the same, since it was mainly legacy stuff that was being changed.
- Btw this change in AHK v2, could cause mayhem with my scripts, it's probably for the best though. I could do with an advanced script parser to help identify instances of this. Problems like these are one reason why I was already working on an advanced script parser.
Last edited by jeeswg on 26 Nov 2017, 19:18, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Nov 2017, 18:56

So it's as simple as creating a new object within the for loop, and that way it can survive outside the for loop?
I guess you are just sloppy with your wording, but to be clear, or nitpick if you like, you are not creating a new object, you are storing another reference to it, which increments its reference-count and hence, the object is not freed when the loop breaks. And yes, it is that simple, in this case.
I will comment more on for loops in conversion logic, v1 = -> v1 := -> v2, two-way compatibility, I think it is more fit to continue there.

Cheers.
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Nov 2017, 19:04

- Thanks, I did mean that. I didn't know it would quite work as you described. So, on that basis, you could increment the reference count of the object which would be a one-line fix?

Code: Select all

for oWinKey in ComObjCreate("Shell.Application").Windows
	if (oWinKey.HWND = hWnd) {
		ObjAddRef(oWinKey)
		break
	}
- Yes, if you have more to say about for loops, do post there.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Nov 2017, 19:20

You still do not have a reference to the object to which oWinKey refers to when the loop breaks since the variable oWinKey is restored to its previous value. However, you have managed to ensure that the object is not going to be properly realeased for the duration of the script run ;). Also, it is objaddref(ptr).
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

26 Nov 2017, 19:25

- Yes, I checked the documentation, add tried ObjAddRef(&oWinKey) also. OK so this complicates editing my functions somewhat, a new object reference is needed for each for loop.
- Thanks very much though, I can go back and make these functions 'AHK v2 ready', which I will do soon.

[EDIT:]
[Here is the documentation, making k and v in for loops, similar to A_Index and A_LoopField/A_LoopXXX in loops.]
For-loop
https://lexikos.github.io/v2/docs/commands/For.htm
When the loop breaks or completes, these variables are restored to their former values.
v2-changes
https://autohotkey.com/v2/v2-changes.htm
For k, v in obj now "localizes" k and v. When the loop breaks or completes, k and v are restored to the values they had before the loop started.
- Btw you stated 'For two-way compatibility, I'd do', but this is how you would do it in AHK v2 anyway, right?
- Btw re. 'object' v. 'object reference', I think I'll start a thread on this, because I believe that both terms can be potentially misleading, as indeed appear to be virtually all words relating to objects.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

27 Nov 2017, 03:45

tried ObjAddRef(&oWinKey) also.
I didn't mean you should try that, I only meant that is the correct way to call the function, my comments was in regards to using the function correctly.
Btw you stated 'For two-way compatibility, I'd do', but this is how you would do it in AHK v2 anyway, right?
Yes, and that is also the only actual reason I would do it.

Cheers.
occap

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

18 Mar 2018, 05:58

I am new in the AHK world, but see the potential of the JEE_ Functions, and eventually would use some of these.

But I started in AHK V2. Therefore my question asking if there is a AHK V2 flavour of these functions.
neogna2
Posts: 37
Joined: 15 Sep 2016, 15:44

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

31 Aug 2018, 17:11

JEE_ExpOpenContainingFolderEx() does not detect the already existing window in Windows 10 because Explorer has a new name there.
To fix that change this line

Code: Select all

if (oWin.Name = "Windows Explorer")
to

Code: Select all

if (oWin.Name = "File Explorer")
or to make the function compatible with both Windows 10 and older Windows versions

Code: Select all

explorer_version := SubStr(A_OSVersion,1,2) = "10" ? "File Explorer" : "Windows Explorer"
if (oWin.Name = explorer_version)
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

31 Aug 2018, 19:08

- @neogna2: Thanks for the info.
- I will probably add in something like this (just the vName one-liner):

Code: Select all

q::
vVersion := DllCall("kernel32\GetVersion", UInt)
;major, minor, build
MsgBox, % Format("{}.{}.{:04}", vVersion & 0xFF, (vVersion >> 8) & 0xFF, (vVersion >> 16) & 0xFFFF)

vName := (DllCall("kernel32\GetVersion", UInt) && 0xFF) >= 10 ? "File Explorer" : "Windows Explorer"
MsgBox, % vName
return
- Apparently GetVersion may not be reliable in future.
- To avoid bloated code, it would help if there was something like: A_OSVersionMajor / A_OSVersionMinor / 'A_OSVersionValue'.
- Also, A_OSVersion at present is changing in AHK v2, to be what I wanted for 'A_OSVersionValue', x.x.xxxx instead of a friendly name. (Code to retrieve a friendly name has to be updated for every Windows OS.)

- [EDIT:] It appears that AHK is no longer adding friendly names to A_OSVersion, which ironically makes it more useful. This is good to see.
Variables and Expressions - Definition & Usage | AutoHotkey
https://autohotkey.com/docs/Variables.htm#OSVersion
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
neogna2
Posts: 37
Joined: 15 Sep 2016, 15:44

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

01 Sep 2018, 14:02

Another issue with JEE_ExpOpenContainingFolderEx() specifically this line

Code: Select all

&& (vDir = oWin.Document.Folder.Self.Path)
If vPath is in a root folder like C:\ and a File Explorer window at C:\ is already open then vDir = "C:" but oWin.Document.Folder.Self.Path = "C:\"
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

01 Sep 2018, 15:58

- Thanks for the info, I don't know why some places are so allergic to 'C:' and insist on adding a trailing backslash. I'll sort that also. I intend to review all of the functions. E.g. I came across new techniques for creating a new folder, and for selecting a file by name.

Code: Select all

;either:
if (StrLen(vDir) = 2)
	vDir .= "\"
;or:
if (vDir = RTrim(oWin.Document.Folder.Self.Path, "\"))
- The question is: are there other folders that can have a trailing backslash?
- RTrim looks like the safer approach.

- Do keep pointing out any bugs or general suggestions. Cheers.

- Btw I've tried to resolve retrieving the OS version here:
A_MajorAHKVersion - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 13&t=53924
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
croselzxcv
Posts: 4
Joined: 08 Dec 2018, 00:33

Re: Explorer window interaction (folder windows/Desktop, file/folder enumeration/selection/navigation/creation)

28 Aug 2019, 20:43

jeeswg wrote:
01 Sep 2018, 15:58
- Thanks for the info, I don't know why some places are so allergic to 'C:' and insist on adding a trailing backslash. I'll sort that also. I intend to review all of the functions. E.g. I came across new techniques for creating a new folder, and for selecting a file by name.

Code: Select all

;either:
if (StrLen(vDir) = 2)
	vDir .= "\"
;or:
if (vDir = RTrim(oWin.Document.Folder.Self.Path, "\"))
- The question is: are there other folders that can have a trailing backslash?
- RTrim looks like the safer approach.

- Do keep pointing out any bugs or general suggestions. Cheers.

- Btw I've tried to resolve retrieving the OS version here:
A_MajorAHKVersion - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=13&t=53924
I'm just using this JEE_ExpOpenContainingFolderEx function and it keeps opening a new window when I want to select a file. In the description it says: ;select file in folder (use existing window, else, open new window)
Is there anyway to remove the opening a new window. I'm running a loop for this to run a script on each file selected, and I'm just getting a new window every time. Help?

OOPS!!! nevermind. A guy above me answered it. I recently started using Windows 10. So I made the necessary changes as mentioned above!

Jesswg Thank you for this br0!!!!! Script works perfectly. SUPER COOL!!!!! It's really hard to find a good file selection script too. Let me know if you need a favor! I owe you! Lemme know: [email protected] || [email protected]

Return to “Scripts and Functions”

Who is online

Users browsing this forum: thebbandit and 38 guests