- Interesting idea, which I've written some code for. I could imagine it being useful for listview/treeview items that indicate different states.
- Did you have any particular programs in mind? (I at least needed some example programs to test it on, fortunately I thought of a few.)
- As ever, save any data before testing the code on any programs.
- I've adapted 2 functions from here, that get listview/treeview text, to get icon image indexes instead.
GUIs via DllCall: text functions (get/set internal/external control text) - AutoHotkey Community
- The code below requires some of the auxiliary functions in that thread.
Code: Select all
;AHK v1 code
;see here for additional functions:
;GUIs via DllCall: text functions (get/set internal/external control text) - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
;tested with NirSoft IECacheView and NirSoft USBDeview
q:: ;get listview item image indexes
ControlGet, hCtl, Hwnd,, SysListView321, A
vOutput := JEE_LVGetImageIndex(hCtl, -1, 0)
Clipboard := vOutput
MsgBox, % vOutput
return
;tested with HTML Help
w:: ;get treeview item image indexes
ControlGet, hCtl, Hwnd,, SysTreeView321, A
vOutput := JEE_TVGetImageIndex(hCtl)
Clipboard := vOutput
MsgBox, % vOutput
return
;==================================================
;adapted from JEE_LVGetText
;vList: 1-based comma-separated list or array
;vList: -1/f/s: all/focused/selected items
;vOpt: m#: e.g. m1000, specify max chars 1000
;vOpt: o: return an object instead of a string
JEE_LVGetImageIndex(hCtl, vList:=-1, vCol:=-1, vSep:="`n", vSepTab:="`t", vOpt:="")
{
local
vErr := A_PtrSize=8 && JEE_WinIs64Bit(hCtl) ? -1 : 0xFFFFFFFF
(vList = "") && (vList := -1)
vScriptPID := DllCall("kernel32\GetCurrentProcessId", "UInt")
vPID := WinGetPID("ahk_id " hCtl)
if (vPID = vScriptPID)
vIsLocal := 1, vPIs64 := (A_PtrSize=8)
else
vIsLocal := 0
;count items (rows) and columns
if !vCount := SendMessage(0x1004, 0, 0,, "ahk_id " hCtl) ;LVM_GETITEMCOUNT := 0x1004
return
if !hLVH := SendMessage(0x101F,,,, "ahk_id " hCtl) ;LVM_GETHEADER := 0x101F
return
if !vCountCol := SendMessage(0x1200,,,, "ahk_id " hLVH) ;HDM_GETITEMCOUNT := 0x1200
return
if (vCountCol = vErr) ;-1
return
if (vCol = -1)
{
vCol := "1"
Loop % vCountCol - 1
vCol .= "," (A_Index+1)
}
if IsObject(vList)
oArray := vList
else if InStr(vList, ",")
oArray := StrSplit(vList, ",")
else if (SubStr(vList, 1, 1) = "f")
{
;LVNI_FOCUSED := 0x1
vIndex := SendMessage(0x100C, -1, 0x1,, "ahk_id " hCtl) ;LVM_GETNEXTITEM := 0x100C
if (vIndex = vErr) ;-1
return
oArray := [vIndex+1]
}
else if (SubStr(vList, 1, 1) = "s")
{
oArray := []
;LVNI_SELECTED := 0x2
vItem := -1
Loop
{
vItem := SendMessage(0x100C, vItem, 0x2,, "ahk_id " hCtl) ;LVM_GETNEXTITEM := 0x100C
if (vItem = vErr) ;-1
break
oArray.Push(vItem+1)
}
}
else if !(vList = -1)
oArray := [vList]
else
oArray := []
if !vIsLocal
{
if !hProc := JEE_DCOpenProcess(0x438, 0, vPID)
return
vIsWow64Process := 0
if A_Is64bitOS && !DllCall("kernel32\IsWow64Process", "Ptr",hProc, "Int*",vIsWow64Process)
return
vPIs64 := !vIsWow64Process
}
vPtrType := vPIs64?"Int64":"Int"
vSize1 := vPIs64?40:28 ;size is typically 88:60
VarSetCapacity(LVITEM, vSize1, 0)
if !vIsLocal
{
if !pBuf := JEE_DCVirtualAllocEx(hProc, 0, vSize1, 0x3000, 0x4)
return
}
else
pBuf := &LVITEM
NumPut(0x2, &LVITEM, 0, "UInt") ;mask ;LVIF_IMAGE := 0x2
if !vIsLocal
JEE_DCWriteProcessMemory(hProc, pBuf, &LVITEM, vSize1, 0)
vMsg := A_IsUnicode?0x104B:0x1005 ;LVM_GETITEMW := 0x104B ;LVM_GETITEMA := 0x1005
if vGetObj := !!InStr(vOpt, "o")
(oOutput := Map()).SetCapacity(vCount)
else
VarSetCapacity(vOutput, 4*vCount << !!A_IsUnicode) ;expect around 2 digits per image index number
Loop % oArray.Length() ? oArray.Length() : vCount
{
vIndex := (vList = -1) ? A_Index-1 : oArray[A_Index]-1
if vGetObj
oOutput[vIndex+1] := []
else
vOutput .= (A_Index=1?"":vSep)
Loop Parse, vCol, % ","
{
NumPut(0, &LVITEM, vPIs64?36:28, "Int") ;iImage
NumPut(vIndex, &LVITEM, 4, "Int") ;iItem
NumPut(A_LoopField-1, &LVITEM, 8, "Int") ;iSubItem
if !vIsLocal
JEE_DCWriteProcessMemory(hProc, pBuf+4, &LVITEM+4, 8, 0)
vRet := SendMessage(A_IsUnicode?0x104B:0x1005, 0, pBuf,, "ahk_id " hCtl) ;LVM_GETITEMW := 0x104B ;LVM_GETITEMA := 0x1005
if vRet && !vIsLocal
JEE_DCReadProcessMemory(hProc, pBuf+(vPIs64?36:28), &LVITEM+(vPIs64?36:28), 4, 0)
;source: CommCtrl.h
;I_IMAGECALLBACK := -1
;I_IMAGENONE := -2
vImageIndex := NumGet(&LVITEM, vPIs64?36:28, "Int") ;iImage
if vGetObj
oOutput[vIndex+1].Push(vImageIndex)
else
vOutput .= (A_Index=1?"":vSepTab) vImageIndex
}
}
if !vIsLocal
{
JEE_DCVirtualFreeEx(hProc, pBuf, 0, 0x8000)
JEE_DCCloseHandle(hProc)
}
if vGetObj
return oOutput
else
return vOutput
}
;==================================================
;adapted from JEE_TVGetText
; ;===============
; ;e.g.
; ;q::
; ControlGet, hCtl, Hwnd,, SysTreeView321, A
; MsgBox, % JEE_TVGetText(hCtl)
; MsgBox, % JEE_TVGetText(hCtl, "f")
; MsgBox, % JEE_TVGetText(hCtl, -1, "`r`n")
; MsgBox, % JEE_TVGetText(hCtl, -1, "`r`n", "", "[DIR]")
; MsgBox, % JEE_TVGetText(hCtl, -1, "`r`n", "p", "[DIR]")
; MsgBox, % JEE_TVGetText(hCtl, -1, "`r`n", "i", "[DIR]")
; MsgBox, % JEE_TVGetText(hCtl, -1, "`r`n", "c")
; MsgBox, % JEE_TVGetText(hCtl, -1, "`r`n", "cp")
; MsgBox, % JEE_TVGetText(hCtl, -1, "`r`n", "icp")
; MsgBox, % JEE_TVGetText(hCtl, -1, "`r`n", "icp", "[DIR]")
; return
; ;===============
; ;===============
; ;e.g.
; ;q:: ;get visible items
; ControlGet, hCtl, Hwnd,, SysTreeView321, A
; ;TVGN_NEXTVISIBLE := 0x6 ;TVGN_FIRSTVISIBLE := 0x5
; oArray := [], hItem := 0
; Loop
; {
; if hItem := SendMessage(0x110A, (A_Index=1)?0x5:0x6, hItem,, "ahk_id " hCtl) ;TVM_GETNEXTITEM := 0x110A
; oArray.Push(hItem)
; else
; break
; }
; MsgBox, % JEE_TVGetText(hCtl, oArray)
; return
; ;===============
;vList: 1-based comma-separated list or array
;vList: -1/f/s: all/focused/selected items
;vOpt: m#: e.g. m1000, specify max chars 1000
;vOpt: o: return an object instead of a string
;further options:
;vOpt: d: get dirs (list items with children)
;vOpt: f: get files (list items with no children)
;vOpt: p: show full paths
;vOpt: i: indentation on
;vOpt: c: parent name column
;vOpt: o: return an object instead of text
;vList: warning: paths/hierarchy information is only expected to be correct when vList:=-1
;vDirPfx: if specified, a column is added that indicates items that are 'dirs' (that have children)
JEE_TVGetImageIndex(hCtl, vList:=-1, vSep:="`n", vOpt:="", vDirPfx:="")
{
local
(vList = "") && (vList := -1)
vScriptPID := DllCall("kernel32\GetCurrentProcessId", "UInt")
vPID := WinGetPID("ahk_id " hCtl)
if (vPID = vScriptPID)
vIsLocal := 1, vPIs64 := (A_PtrSize=8)
else
vIsLocal := 0
if !vCount := SendMessage(0x1105,,,, "ahk_id " hCtl) ;TVM_GETCOUNT := 0x1105
return
if IsObject(vList)
oArray := vList
else if InStr(vList, ",")
oArray := StrSplit(vList, ",")
else if (SubStr(vList, 1, 1) = "f")
|| (SubStr(vList, 1, 1) = "s")
{
;TVGN_CARET := 0x9
hItem := SendMessage(0x110A, 0x9, 0,, "ahk_id " hCtl) ;TVM_GETNEXTITEM := 0x110A
oArray := [hItem]
}
else if !(vList = -1)
oArray := [vList]
else if (vList = -1)
{
;TVGN_ROOT := 0x0
hItemNext := SendMessage(0x110A, 0x0, 0,, "ahk_id " hCtl) ;TVM_GETNEXTITEM := 0x110A
oArray := []
}
else
oArray := []
vMsg := A_IsUnicode?0x113E:0x110C ;TVM_GETITEMW := 0x113E ;TVM_GETITEMA := 0x110C
if !vIsLocal
{
if !hProc := JEE_DCOpenProcess(0x438, 0, vPID)
return
vIsWow64Process := 0
if A_Is64bitOS && !DllCall("kernel32\IsWow64Process", "Ptr",hProc, "Int*",vIsWow64Process)
return
vPIs64 := !vIsWow64Process
}
vPtrType := vPIs64?"Int64":"Int"
vSize1 := vPIs64?56:40
VarSetCapacity(TVITEM, vSize1, 0)
if !vIsLocal
{
if !pBuf := JEE_DCVirtualAllocEx(hProc, 0, vSize1, 0x3000, 0x4)
return
}
else
pBuf := &TVITEM
NumPut(0x2, &TVITEM, 0, "UInt") ;mask ;TVIF_IMAGE := 0x2
if !vIsLocal
JEE_DCWriteProcessMemory(hProc, pBuf, &TVITEM, vSize1, 0)
vMsg := A_IsUnicode?0x113E:0x110C ;TVM_GETITEMW := 0x113E ;TVM_GETITEMA := 0x110C
vGen := 1
if !InStr(vOpt, "d") && !InStr(vOpt, "f")
vOpt .= "df"
vOffset := vPIs64?8:4
if vGetObj := !!InStr(vOpt, "o")
(oOutput := []).SetCapacity(vCount)
else
VarSetCapacity(vOutput, 4*vCount << !!A_IsUnicode) ;expect around 2 digits per image index number
Loop % oArray.Length() ? oArray.Length() : vCount
{
hItem := (vList = -1) ? hItemNext : oArray[A_Index]
vHasSibling := vHasChild := 0
;==============================
;get next element: child, else sibling, else ancestor's sibling
;check for child
;TVGN_CHILD := 0x4
hItemNext := SendMessage(0x110A, 0x4, hItem,, "ahk_id " hCtl) ;TVM_GETNEXTITEM := 0x110A
if hItemNext
vHasChild := 1
;check for sibling
if !vHasChild
{
;TVGN_NEXT := 0x1
hItemNext := SendMessage(0x110A, 0x1, hItem,, "ahk_id " hCtl) ;TVM_GETNEXTITEM := 0x110A
if hItemNext
vHasSibling := 1
}
;check for ancestor's sibling (find first ancestor with a sibling)
vHasSibling2 := 0
if !vHasChild && !vHasSibling
{
vGenNext := vGen, hItemNext := hItem
Loop
{
if (vGenNext = 1)
{
hItemNext := 0
break
}
;get parent
;TVGN_PARENT := 0x3
hItemNext := SendMessage(0x110A, 0x3, hItemNext,, "ahk_id " hCtl) ;TVM_GETNEXTITEM := 0x110A
vGenNext--
;check for sibling
;TVGN_NEXT := 0x1
hItemNext2 := SendMessage(0x110A, 0x1, hItemNext,, "ahk_id " hCtl) ;TVM_GETNEXTITEM := 0x110A
if hItemNext2
{
hItemNext := hItemNext2, vHasSibling2 := 1
break
}
}
}
;==============================
NumPut(0, &TVITEM, vPIs64?36:24, "Int") ;iImage
NumPut(hItem, &TVITEM, vPIs64?8:4, vPtrType) ;hItem
if !vIsLocal
JEE_DCWriteProcessMemory(hProc, pBuf+vOffset, &TVITEM+vOffset, vOffset, 0)
vRet := SendMessage(vMsg, 0, pBuf,, "ahk_id " hCtl) ;TVM_GETITEMW := 0x113E ;TVM_GETITEMA := 0x110C
if vRet && !vIsLocal
JEE_DCReadProcessMemory(hProc, pBuf+(vPIs64?36:24), &TVITEM+(vPIs64?36:24), 4, 0)
;source: CommCtrl.h
;I_IMAGECALLBACK := -1
;I_IMAGENONE := -2
vImageIndex := NumGet(&TVITEM, vPIs64?36:24, "Int") ;iImage
if vHasChild
vDir%vGen% := vImageIndex
vGenX := vGen-1
if (InStr(vOpt, "d") && vHasChild)
|| (InStr(vOpt, "f") && !vHasChild)
{
vTemp2 := ""
if InStr(vOpt, "c")
vTemp2 .= vDir%vGenX% "`t"
if !(vDirPfx = "")
vTemp2 .= (vHasChild ? vDirPfx : "") "`t"
if InStr(vOpt, "i")
vTemp2 .= JEE_StrRept("`t", vGen-1)
if InStr(vOpt, "p")
{
Loop % vGenX
vTemp2 .= vDir%A_Index% "\"
}
if vGetObj
oOutput.Push(vTemp2 vImageIndex)
else
vOutput .= vTemp2 vImageIndex vSep
}
if vHasChild
vGen++
if vHasSibling2
vGen := vGenNext
if !hItemNext
break
}
if !vIsLocal
{
JEE_DCVirtualFreeEx(hProc, pBuf, 0, 0x8000)
JEE_DCCloseHandle(hProc)
}
if vGetObj
return oOutput
else
return SubStr(vOutput, 1, -StrLen(vSep))
}
;==================================================
- Btw nice avatar. Cheers.