Extract icon index from ListView/TreeView item/row Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Extract icon index from ListView/TreeView item/row  Topic is solved

26 Oct 2019, 09:40

Is there a way to extract an icon index from a ListView/TreeView row/item? Of course the index would be in relation to the associated ImageList.

I've looked up several SendMessage codes to try and at least get a bearing on where to start. Having some issues determining of this is even possible?

EDIT: I gotta also give credit to @just me who figured it out before I did for ListView...

EDIT:

Return values are zero-based. You can specify icon indexes without an ImageList and still retrieve the stored "phantom index".

Code: Select all

; ====================================================================
; TreeGetIconIndex(hCtl,hItem) ; gets tree item icon index ; support function
; NOTE: you can store a "phantom icon index" and retrieve it without an ImageList if you wish
;       hCtl = control/TreeView hwnd        hItem = node ID from TV_GetNext() or TV_GetSelection()
; return values are ZERO BASED
; ====================================================================

TreeGetIconIndex(hCtl,hItem) {
	vPIs64 := (A_PtrSize=8) ; determine system arch
	vPtrType := vPIs64?"Int64":"Int" ; set data type
	vSize1 := vPIs64?56:40 ; set pointer size
	
	VarSetCapacity(TVITEM, vSize1, 0) ; make variable/structure
	pBuf := &TVITEM ; capture pointer to structure
	NumPut(0x2, &TVITEM, 0, "UInt") ;mask ;TVIF_IMAGE := 0x2 ; define that we want the img index
	
	vMsg := A_IsUnicode?0x113E:0x110C ;TVM_GETITEMW := 0x113E ;TVM_GETITEMA := 0x110C ; define msg according to system arch
	vOffset := vPIs64?8:4 ; set offset according to system arch
	
	NumPut(0, &TVITEM, vPIs64?36:24, "Int") ;iImage
	NumPut(hItem, &TVITEM, vPIs64?8:4, vPtrType) ;hItem ; put item handle into structure
	
	SendMessage, %vMsg%, 0, %pBuf%,, ahk_id %hCtl% ;TVM_GETITEMW := 0x113E ;TVM_GETITEMA := 0x110C ; get img index
	vRet := ErrorLevel
	vImageIndex := NumGet(&TVITEM, vPIs64?36:24, "Int") ;iImage ; extract img index from structure
	
	return vImageIndex
}

; ====================================================================
; ListGetIconIndex(hCtl,vIndex) ; gets list item icon index ; support function
; NOTE: you can store a "phantom icon index" and retrieve it without an ImageList if you wish
;       it is possible to also get icon indexes for other columns
;       hCtl = control/TreeView hwnd        hItem = node ID from TV_GetNext() or TV_GetSelection()
; return values are ZERO BASED
; ====================================================================

ListGetIconIndex(hCtl,vIndex,vCol = 1) {
	vIndex := vIndex - 1 ; row number must be zero-based
	
	vPIs64 := (A_PtrSize=8) ; determine system arch
	vPtrType := vPIs64?"Int64":"Int" ; set data type
	vSize1 := vPIs64?56:40 ; set pointer size
	
	VarSetCapacity(LVITEM, vSize1, 0) ; create variable/structure
	pBuf := &LVITEM ; capture pointer to structure
	NumPut(0x2, &LVITEM, 0, "UInt") ;mask ;LVIF_IMAGE := 0x2
	
	vMsg := A_IsUnicode?0x104B:0x1005 ;LVM_GETITEMW := 0x104B ;LVM_GETITEMA := 0x1005
	
	NumPut(0, &LVITEM, vPIs64?36:28, "Int") ;iImage
	NumPut(vIndex, &LVITEM, 4, "Int") ;iItem
	NumPut(vCol - 1, &LVITEM, 8, "Int") ; Column number
	
	SendMessage, %vMsg%, 0, pBuf,, ahk_id %hCtl% ;LVM_GETITEMW := 0x104B ;LVM_GETITEMA := 0x1005
	vImageIndex := NumGet(&LVITEM, vPIs64?36:28, "Int") ;iImage
	
	return vImageIndex
}
BIG thanks to jeeswg for his code that helped point the way for me.

@just me's version:

Code: Select all

; --------------------------------------------------------------------------------------------------------------------------------
; LVM_GETITEM -> docs.microsoft.com/en-us/windows/win32/controls/lvm-getitem
; LVITEMW     -> docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-lvitemw
; --------------------------------------------------------------------------------------------------------------------------------
LV_GetIconIndex(HLV, Row, Col := 1) { ; HLV: handle to the ListView control
   Static LVM_GETITEM := A_IsUnicode ? 0x104B : 0x1005 ; LVM_GETITEMW : LVM_GETITEMA
   Static SizeOfLVITEM := 40 + (A_PtrSize * 5)
   VarSetCapacity(LVITEM, SizeOfLVITEM, 0)
   NumPut(0x0002,  LVITEM, 0, "UInt") ; LVIF_IMAGE
   NumPut(Row - 1, LVITEM, 4, "Int")
   NumPut(Col - 1, LVITEM, 8, "Int")
   If DllCall("SendMessage", "Ptr", HLV, "UInt", LVM_GETITEM, "Ptr", 0, "Ptr", &LVITEM, "UInt")
      Return (NumGet(LVITEM, 20 + (A_PtrSize * 2), "Int") + 1)
   Return False
}
Last edited by TheArkive on 23 Dec 2019, 04:07, edited 7 times in total.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Extract icon index from ListView/TreeView item/row

31 Oct 2019, 16:37

- 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
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
- 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.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
just me
Posts: 9487
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Extract icon index from ListView/TreeView item/row

31 Oct 2019, 17:03

If the controls belong to an AHK GUI, this might be an example for a ListView control:

Code: Select all

; --------------------------------------------------------------------------------------------------------------------------------
; LVM_GETITEM -> docs.microsoft.com/en-us/windows/win32/controls/lvm-getitem
; LVITEMW     -> docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-lvitemw
; --------------------------------------------------------------------------------------------------------------------------------
LV_GetIconIndex(HLV, Row, Col := 1) { ; HLV: handle to the ListView control
   Static LVM_GETITEM := A_IsUnicode ? 0x104B : 0x1005 ; LVM_GETITEMW : LVM_GETITEMA
   Static SizeOfLVITEM := 40 + (A_PtrSize * 5)
   VarSetCapacity(LVITEM, SizeOfLVITEM, 0)
   NumPut(0x0002,  LVITEM, 0, "UInt") ; LVIF_IMAGE
   NumPut(Row - 1, LVITEM, 4, "Int")
   NumPut(Col - 1, LVITEM, 8, "Int")
   If DllCall("SendMessage", "Ptr", HLV, "UInt", LVM_GETITEM, "Ptr", 0, "Ptr", &LVITEM, "UInt")
      Return (NumGet(LVITEM, 20 + (A_PtrSize * 2), "Int") + 1)
   Return False
}
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: Extract icon index from ListView/TreeView item/row

06 Nov 2019, 02:09

jeeswg wrote:
31 Oct 2019, 16:37
- 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.)
...
- Btw nice avatar. Cheers.

Thanks! This will help. I actually posted a function that dumps the data/structure of a tree in plain text, and another function that reads it down to load the tree just as it was when saved, and I was hoping to try and add the icon index to this info. Would your code handle exceptions where there is no ImageList? I'll get around to trying it soon. Thanks again!

As you mentioned, yes I was using the icon in this case to indicate the status of a particular node/item with the icon, although I haven't posted any examples yet.

I'm currently writing a program to save profiles that encompass the StartMode of all system services, and the user of course determines the profile name. I'm also including registry entries that run on system start that will be enabled/disabled according to the user's selection, as well as setting the state of Tasks in the Task Manager. I use the icon to more quickly see (with color code) if a service is running or not (red / green) and the letter indicates "Auto", "Manual", or "Disabled". So that's a 6 icons: Red A, Green A, Red D, Green D, Red M, Green M. Within this program, I've created a function that reads down service data with a WMI query and then creates a TreeView so the user can see the nested heirarchy of services, so then the user can determine what other services would be affected by stopping any particular service.

I'm trying to create a complete tool for managing what runs on startup, mostly for performance boost and power saving purposes.

If you would like I can send you what I'm currently working on...
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: Extract icon index from ListView/TreeView item/row

06 Nov 2019, 02:12

just me wrote:
31 Oct 2019, 17:03
If the controls belong to an AHK GUI, this might be an example for a ListView control:

Code: Select all

; --------------------------------------------------------------------------------------------------------------------------------
; LVM_GETITEM -> docs.microsoft.com/en-us/windows/win32/controls/lvm-getitem
; LVITEMW     -> docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-lvitemw
; --------------------------------------------------------------------------------------------------------------------------------
LV_GetIconIndex(HLV, Row, Col := 1) { ; HLV: handle to the ListView control
   Static LVM_GETITEM := A_IsUnicode ? 0x104B : 0x1005 ; LVM_GETITEMW : LVM_GETITEMA
   Static SizeOfLVITEM := 40 + (A_PtrSize * 5)
   VarSetCapacity(LVITEM, SizeOfLVITEM, 0)
   NumPut(0x0002,  LVITEM, 0, "UInt") ; LVIF_IMAGE
   NumPut(Row - 1, LVITEM, 4, "Int")
   NumPut(Col - 1, LVITEM, 8, "Int")
   If DllCall("SendMessage", "Ptr", HLV, "UInt", LVM_GETITEM, "Ptr", 0, "Ptr", &LVITEM, "UInt")
      Return (NumGet(LVITEM, 20 + (A_PtrSize * 2), "Int") + 1)
   Return False
}
Thanks for that. I'm currently focusing on a TreeView, but I plan to do the same for ListView as well.

EDIT: of course this works perfectly fine! And it's shorter than my version...
Last edited by TheArkive on 23 Dec 2019, 03:48, edited 1 time in total.
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Extract icon index from ListView/TreeView item/row

06 Nov 2019, 04:30

You could as well store the status/ID of the icon in a separate array. You would then have to update/sync the treeview and the array all the time.
ciao
toralf
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: Extract icon index from ListView/TreeView item/row

06 Nov 2019, 04:38

toralf wrote:
06 Nov 2019, 04:30
You could as well store the status/ID of the icon in a separate array. You would then have to update/sync the treeview and the array all the time.
Right, that's what I'm doing now. I'm hoping to make this process programatic so it doesn't have to be known / constantly monitored. Hopefully if this is possible it will also be efficient.
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Extract icon index from ListView/TreeView item/row

06 Nov 2019, 04:56

Yes, would reduce bookkeeping. I would use the technique as well when all info is in the control.
But if there is more info then i’ll have to use an array anyway.
ciao
toralf
just me
Posts: 9487
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Extract icon index from ListView/TreeView item/row

06 Nov 2019, 05:09

TVM_GETITEM will do it for a TreeView.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: Extract icon index from ListView/TreeView item/row

21 Dec 2019, 13:51

--== deleted ==--
Last edited by TheArkive on 23 Dec 2019, 02:25, edited 1 time in total.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: Extract icon index from ListView/TreeView item/row

23 Dec 2019, 01:44

Finally got it, a simple programatic way to extract the icon index. And I found out something very interesting in the process.

If you have code that populates a tree and defines image indexes WITHOUT an actual ImageList, then of course there will be no icons, however the "phantom icon index" will still be stored and can still be retrieved.

There is of course no visual indication at all of what the index is. It's more like "invisible metadata".

Code: Select all

; ====================================================================
; TreeGetIconIndex(hCtl,hItem) ; gets tree item icon index
; NOTE: you can store a "phantom icon index" and retrieve it without an ImageList if you wish
; ====================================================================

TreeGetIconIndex(hCtl,hItem) {
	vPIs64 := (A_PtrSize=8) ; determine system arch
	vPtrType := vPIs64?"Int64":"Int" ; set data type
	vSize1 := vPIs64?56:40 ; set pointer size
	
	VarSetCapacity(TVITEM, vSize1, 0) ; make variable/structure in memory
	pBuf := &TVITEM ; capture pointer to structure
	NumPut(0x2, &TVITEM, 0, "UInt") ;mask ;TVIF_IMAGE := 0x2 ; define that we want the img index
	
	vMsg := A_IsUnicode?0x113E:0x110C ;TVM_GETITEMW := 0x113E ;TVM_GETITEMA := 0x110C ; define msg according to system arch
	vOffset := vPIs64?8:4 ; set offset according to system arch
	
	NumPut(0, &TVITEM, vPIs64?36:24, "Int") ;iImage
	NumPut(hItem, &TVITEM, vPIs64?8:4, vPtrType) ;hItem ; put item handle into structure
	
	SendMessage, %vMsg%, 0, %pBuf%,, ahk_id %hCtl% ;TVM_GETITEMW := 0x113E ;TVM_GETITEMA := 0x110C ; get img index
	vRet := ErrorLevel
	vImageIndex := NumGet(&TVITEM, vPIs64?36:24, "Int") ;iImage ; extract img index from structure
	
	return vImageIndex
}
I'm going to work this into my function that saves and loads a tree structure and update that post soon!

EDIT: Last caveat ... if you don't even try to store a "phantom icon index" then all return values are zero. This is slightly problematic because the return value for valid icon indexes is zero-based. So there isn't much error checking that can be done. The user has to implement some form of knowing when "0 = 1" and when "0 = nothing". The obvious answer is that there will be no ImageList so maybe that can be easily incorporated.

EDIT 2: Super big thanks to @jeeswg!! Without his code I wouldn't have known where to start.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: Extract icon index from ListView/TreeView item/row

23 Dec 2019, 03:24

In case anyone finds this useful, I looked at the code from @jeeswg and wrote the same for a list view.

It seems to follow the same rules, meaning that you can store a "phantom icon index" witout an ImageList.

Code: Select all

; ====================================================================
; ListGetIconIndex(hCtl,vIndex) ; gets list item icon index ; support function
; NOTE: you can store a "phantom icon index" and retrieve it without an ImageList if you wish
; ====================================================================

ListGetIconIndex(hCtl,vIndex) {
	vIndex := vIndex - 1 ; row number must be zero-based
	
	vPIs64 := (A_PtrSize=8) ; determine system arch
	vPtrType := vPIs64?"Int64":"Int" ; set data type
	vSize1 := vPIs64?56:40 ; set pointer size
	
	VarSetCapacity(LVITEM, vSize1, 0) ; create variable/structure
	pBuf := &LVITEM ; capture pointer to structure
	NumPut(0x2, &LVITEM, 0, "UInt") ;mask ;LVIF_IMAGE := 0x2
	
	vMsg := A_IsUnicode?0x104B:0x1005 ;LVM_GETITEMW := 0x104B ;LVM_GETITEMA := 0x1005
	
	NumPut(0, &LVITEM, vPIs64?36:28, "Int") ;iImage
	NumPut(vIndex, &LVITEM, 4, "Int") ;iItem
	
	SendMessage, %vMsg%, 0, pBuf,, ahk_id %hCtl% ;LVM_GETITEMW := 0x104B ;LVM_GETITEMA := 0x1005
	vImageIndex := NumGet(&LVITEM, vPIs64?36:28, "Int") ;iImage
	
	return vImageIndex
}

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: arrondark and 346 guests