Get Treeview Node Icon?

BlitzMax Forums/BlitzMax GUI Programming/Get Treeview Node Icon?

I am writing a programme which catalogues DVD/CD data disks so that the user can search for archived files and know which DVD/CD they are on. To do this I read the directory structure and store it in a Treeview in traditional Windows Explorer style - setting the icon value for each node according to whether it's a drive, directory or file.

I would like to be able to read the icon value of a Treeview node in order to:

1) know when to toggle an icon between an open-folder and closed-folder using ModifyTreeViewNode when the user double clicks a folder

2) save each node's icon value when writing the Treeview node structure to the database [I currently do this by keeping track of each node's icon in a separate array, but this is not very elegant as the info I want is already stored within the Treeview structure - and I am therefore duplicating data]

I have been unable to find a way to retrieve the icon value of a Treeview node. Can anyone please tell me whether this is possible?

For windows. I'm not sure how much of this header you'll need, don't have a lot of time to filter it out for you, but the two functions below should do what you want.

Extern "win32"
	Function SendMessage:Int(hWnd:Int,MSG:Int,wParam:Int,lParam:Int) = "SendMessageA@16"
	Function SetWindowLong:Int(hWnd:Int,nIndex:Int,lNewLong:Long)= "SetWindowLongA@12"
	Function GetModuleHandleA:Int(lMod:Long)'Function CreateWindowExA(dwExStyle:Double,lpClassName:Byte Ptr,lpWindowName:Byte Ptr,dwStyle:Double,x:Int,y:Int,nWidth:Int,nHeight:Int,hWndParent:Int,HMENU:Int,HINSTANCE:Int,LPVOID:Int)
	Function GetWindowLong:Int(hWnd:Int,nIndex:Int)= "GetWindowLongA@8"
	Function MoveWindow(hWnd:Int,X:Int,Y:Int,nWidth:Int,nHeight:Int,bRepaint:Byte)
	Function SetWindowPos:Int( hwnd:Int, hwndafter:Int, x:Int,y:Int, cx:Int,cy:Int, flags:Int)
	Function RedrawWindow:Int( hwnd:Int, rect:Byte Ptr, region:Int, flags:Int)
End Extern

Const SWP_DRAWFRAME:Int = 32
Const SWP_FRAMECHANGED:Int = 32
Const SWP_HIDEWINDOW:Int = 128
Const SWP_NOACTIVATE:Int = 16
Const SWP_NOCOPYBITS:Int = 256
Const SWP_NOMOVE:Int = 2
Const SWP_NOSIZE:Int = 1
Const SWP_NOREDRAW:Int = 8
Const SWP_NOZORDER:Int = 4
Const SWP_SHOWWINDOW:Int = 64
Const SWP_NOOWNERZORDER:Int = 512
Const SWP_NOREPOSITION:Int = 512
Const SWP_NOSENDCHANGING:Int = 1024
Const SWP_DEFERERASE:Int = 8192
Const SWP_ASYNCWINDOWPOS:Int =  16384

Const RDW_ERASE:Int = 4
Const RDW_FRAME:Int = 1024
Const RDW_INTERNALPAINT:Int = 2
Const RDW_INVALIDATE:Int = 1
Const RDW_NOERASE:Int = 32
Const RDW_NOFRAME:Int = 2048
Const RDW_NOINTERNALPAINT:Int = 16
Const RDW_VALIDATE:Int = 8
Const RDW_ERASENOW:Int = 512
Const RDW_UPDATENOW:Int = 256
Const RDW_ALLCHILDREN:Int = 128
Const RDW_NOCHILDREN:Int = 64

Const WS_BORDER:Int = $800000 ' thin border
Const WS_EX_CLIENTEDGE:Int = 512 ' 3d border


' Tree view
Const TVS_HASBUTTONS:Int        = $0001
Const TVS_HASLINES:Int          = $0002
Const TVS_LINESATROOT:Int       = $0004
Const TVS_EDITLABELS:Int        = $0008
Const TVS_DISABLEDRAGDROP:Int   = $0010
Const TVS_SHOWSELALWAYS:Int     = $0020
Const TVS_RTLREADING:Int        = $0040
Const TVS_NOTOOLTIPS:Int        = $0080
Const TVS_CHECKBOXES:Int        = $0100
Const TVS_TRACKSELECT:Int       = $0200
Const TVS_SINGLEEXPAND:Int 	    = $0400
Const TVS_INFOTIP:Int      	    = $0800
Const TVS_FULLROWSELECT:Int	    = $1000
Const TVS_NOSCROLL:Int     	    = $2000
Const TVS_NONEVENHEIGHT:Int	    = $4000

Const TVS_SHAREDIMAGELISTS:Int  = $0000
Const TVS_PRIVATEIMAGELISTS:Int = $0400

Const TV_FIRST:Int				= $1100
Const TVM_GETITEMRECT:Int 		= (TV_FIRST + 4)
Const TVM_SETIMAGELIST:Int 		= (TV_FIRST + 9)
Const TVM_HITTEST:Int 			= (TV_FIRST + 17)
Const TVM_SORTCHILDRENCB:Int 	= (TV_FIRST + 21)
Const TVM_GETITEMW:Int 			= (TV_FIRST + 62)
Const TVM_SETITEMW:Int 			= (TV_FIRST + 63)
Const TVM_INSERTITEMW:Int 		= (TV_FIRST + 50)
Const TVM_GETITEM:Int 			= TV_FIRST + 62
Const TVM_SETITEM:Int 			= TV_FIRST + 13
Const TVM_GETNEXTITEM:Int 		= TV_FIRST + 10
Const TVM_GETITEMSTATE:Int 		= TV_FIRST + 39
Const TVM_GETITEM32A:Int 		= (TV_FIRST+12)
Const TVM_GETITEM32W:Int 		= (TV_FIRST+62)
Const TVM_GETCOUNT:Int 			= (TV_FIRST+5)
Const TVM_SELECTITEM:Int 		= (TV_FIRST+11)
Const TVM_SORTCHILDREN:Int 		= (TV_FIRST+19)
Const TVIS_EXPANDED:Int 		= $20
Const TVSIL_NORMAL:Int 			= 0
Const TVSIL_STATE:Int 			= 2
Const TVGN_NEXT:Int 			= 1
Const TVGN_CHILD:Int 			= 4
Const TVGN_CARET:Int 			= $9

Const GWL_STYLE:Int 			= -$10

Type TVITEM
    Field mask:Int
    Field hItem:Int			'HTREEITEM 
    Field state:Int
    Field stateMask:Int
    Field pszText:Byte Ptr 	'LPTSTR 
    Field cchTextMax:Int
    Field iImage:Int
    Field iSelectedImage:Int
    Field cChildren:Int
    Field lParam:Int			'LPARAM
EndType


' List box
Const LBS_NOTIFY:Int            = $1
Const LBS_SORT:Int              = $2
Const LBS_NOREDRAW:Int          = $4
Const LBS_MULTIPLESEL:Int       = $8
Const LBS_OWNERDRAWFIXED:Int    = $10
Const LBS_OWNERDRAWVARIABLE:Int = $20
Const LBS_HASSTRINGS:Int        = $40
Const LBS_USETABSTOPS:Int       = $70
Const LBS_NOINTEGRALHEIGHT:Int  = $100
Const LBS_MULTICOLUMN:Int       = $200
Const LBS_WANTKEYBOARDINPUT:Int = $400
Const LBS_EXTENDEDSEL:Int       = $800
Const LBS_DISABLENOSCROLL:Int   = $100
Const LBS_NODATA:Int            = $2000
Const LBS_NOSEL:Int             = $4000
Const LBS_STANDARD:Int          = $a00003


Const LVM_FIRST:Int = $1000
Const LVM_GETITEMA:Int          = (LVM_FIRST+5)
Const LVM_SETITEMA:Int          = (LVM_FIRST+6)
Const LVM_INSERTITEMA:Int       = (LVM_FIRST+7)
Const LVM_DELETEITEM:Int        = (LVM_FIRST+8)
Const LVM_DELETEALLITEMS:Int    = (LVM_FIRST+9)
Const LVM_GETCALLBACKMASK:Int   = (LVM_FIRST+10)
Const LVM_SETCALLBACKMASK:Int   = (LVM_FIRST+11)
Const LVM_GETCOLUMNA:Int        = (LVM_FIRST+25)
Const LVM_SETCOLUMNA:Int        = (LVM_FIRST+26)
Const LVM_INSERTCOLUMNA:Int     = (LVM_FIRST+27)
Const LVM_DELETECOLUMN:Int      = (LVM_FIRST+28)
Const LVM_GETCOLUMNWIDTH:Int    = (LVM_FIRST+29)
Const LVM_SETCOLUMNWIDTH:Int    = (LVM_FIRST+30)
Const LVM_GETTEXTCOLOR:Int      = (LVM_FIRST+35)
Const LVM_SETTEXTCOLOR:Int      = (LVM_FIRST+36)
Const LVM_GETTEXTBKCOLOR:Int    = (LVM_FIRST+37)
Const LVM_SETTEXTBKCOLOR:Int    = (LVM_FIRST+38)
Const LVM_SORTITEMS:Int         = (LVM_FIRST+48)
Const LVM_SETLISTBOXEXSTYLE:Int = (LVM_FIRST+54)
Const LVM_GETITEMW:Int          = (LVM_FIRST+75)
Const LVM_SETITEMW:Int          = (LVM_FIRST+76)
Const LVM_INSERTITEMW:Int       = (LVM_FIRST+77)
Const LVM_GETCOLUMNW:Int        = (LVM_FIRST+95)
Const LVM_SETCOLUMNW:Int        = (LVM_FIRST+96)
Const LVM_INSERTCOLUMNW:Int     = (LVM_FIRST+97)

Const LVCF_FMT:Int     = $1
Const LVCF_WIDTH:Int   = $2
Const LVCF_TEXT:Int    = $4
Const LVCF_SUBITEM:Int = $8
Const LVCF_IMAGE:Int   = $10
Const LVCF_ORDER:Int   = $20

Const LVS_ALIGNTOP:Int        = $0
Const LVS_ICON:Int            = $0
Const LVS_REPORT:Int          = $1
Const LVS_SMALLICON:Int       = $2
Const LVS_LIST:Int            = $3
Const LVS_TYPEMASK:Int        = $3
Const LVS_SINGLESEL:Int       = $4
Const LVS_SHOWSELALWAYS:Int   = $8
Const LVS_SORTASCENDING:Int   = $10
Const LVS_SORTDESCENDING:Int  = $20
Const LVS_SHAREIMAGELISTS:Int = $40
Const LVS_NOLABELWRAP:Int     = $80
Const LVS_AUTOARRANGE:Int     = $100
Const LVS_EDITLABELS:Int      = $200
Const LVS_OWNERDRAWFIXED:Int  = $400
Const LVS_ALIGNLEFT:Int       = $800
Const LVS_ALIGNMASK:Int       = $C00
Const LVS_NOSCROLL:Int        = $2000
Const LVS_NOCOLUMNHEADER:Int  = $4000
Const LVS_NOSORTHEADER:Int    = $8000
Const LVS_TYPESTYLEMASK:Int   = $FC00

Const LVS_EX_GRIDLINES:Int        = $1
Const LVS_EX_SUBITEMIMAGES:Int    = $2
Const LVS_EX_CHECKBOXES:Int       = $4
Const LVS_EX_TRACKSELECT:Int      = $8
Const LVS_EX_HEADERDRAGDROP:Int   = $10
Const LVS_EX_FULLROWSELECT:Int    = $20
Const LVS_EX_ONECLICKACTIVATE:Int = $40
Const LVS_EX_TWOCLICKACTIVATE:Int = $80
Const LVS_EX_FLATSB:Int           = $100
Const LVS_EX_REGIONAL:Int         = $200
Const LVS_EX_INFOTIP:Int          = $400
Const LVS_EX_UNDERLINEHOT:Int     = $800
Const LVS_EX_UNDERLINECOLD:Int    = $1000
Const LVS_EX_MULTIWORKAREAS:Int   = $2000
Const LVS_EX_LABELTIP:Int         = $4000
Const LVS_EX_BORDERSELECT:Int     = $8000
Const LVS_EX_DOUBLEBUFFER:Int     = $10000
Const LVS_EX_HIDELABELS:Int       = $20000
Const LVS_EX_SINGLEROW:Int        = $40000
Const LVS_EX_SNAPTOGRID:Int       = $80000
Const LVS_EX_SIMPLESELECT:Int     = $100000

Const LVIF_TEXT:Int        = $1
Const LVIF_IMAGE:Int       = $2
Const LVIF_PARAM:Int       = $4
Const LVIF_STATE:Int       = $8
Const LVIF_INDENT:Int      = $10
Const LVIF_GROUPID:Int     = $100
Const LVIF_COLUMNS:Int     = $200
Const LVIF_NORECOMPUTE:Int = $800 
Const LVIF_DI_SETITEM:Int  = $1000

Type  LVCOLUMN  
	Field mask:Int
	Field fmt:Int
	Field cx:Int
	Field pszText:Byte Ptr
	Field cchTextMax:Int
	Field iSubItem:Int
EndType

Type LVITEM 
	Field mask:Int
	Field iItem:Int
	Field iSubItem:Int
	Field iState:Int
	Field stateMask:Int
	Field pszText:Byte Ptr
	Field cchTextMax:Int
	Field iImage:Int
	Field lParam:Int
	Field iIndent:Int
	Field iGroupId:Int
	Field cColumns:Int
	Field puColumns:Int
EndType


The functions:

Function TreeViewGetNodeImage:Int(TreeView:TGadget, Node:TGadget)
	Local Item:TVITEM = New TVITEM, pItem:Byte Ptr = Item
	Local hwndView:Int, hwndNode:Int

	hwndView = QueryGadget(TreeView, QUERY_HWND)
'	hwndNode = QueryGadget(Node, 1)
	hwndNode = SendMessage(hwndView, TVM_GETNEXTITEM, TVGN_CARET, 0)

	Print "hwndView = " + String(hwndView) + " hwndNode = " + String(hwndNode)
	Item.hItem = hwndNode
	Item.Mask = TVIF_IMAGE
	
	SendMessage(hwndView, TVM_GETITEM, 0, Int(pItem))
	Return Item.iImage
EndFunction

Function TreeViewSetNodeImage:Int(TreeView:TGadget, Node:TGadget, Image:Int)
	Local Item:TVITEM = New TVITEM, pItem:Byte Ptr = Item
	Local hwndView:Int, hwndNode:Int
	
	hwndView = QueryGadget(TreeView, QUERY_HWND)
'	hwndNode = QueryGadget(Node, 1)
	hwndNode = SendMessage(hwndView, TVM_GETNEXTITEM, TVGN_CARET, 0)


	Print "hwndView = " + String(hwndView) + " hwndNode = " + String(hwndNode)
	Item.hItem = hwndNode
	Item.Mask = TVIF_IMAGE
	Item.iImage = Image

	SendMessage(hwndView, TVM_SETITEM, 0, Int(pItem))
	Print "Set icon to " + Item.iImage
	Return Item.iImage
EndFunction


I might of gotten these somewhere on this forum - might not have. I don't have a note of it but it is in a pile of Win32 API code that I have gotten from various places and written myself. Apologies if this is verbatim copied without attribution!

You'll want to remove the Print lines from these in production code.

Many thanks Blueapples - that will work fine for changing an icon image when the user selects a node (in which case the Node parm in the function definition is not required).

Since TVGN_CARET is used to return a handle to the currently selected node, I cannot use the same code to retrieve icon values for all nodes in the treeview. What I need is a similar function to which I can pass a node - but I couldn't seem to get the supplied one to work using the Node parm as hwnd=QueryGadget(Node,QUERY_HWND) always returns zero.
I will keep trying...

Well I managed to get it to work using SelectTreeViewNode but this auto-expanded all the nodes in the treeview. This wouldn't matter if I could turn off the refresh so that this was not visible as I could re-collapse them all once I had finished processing them. I seem to remember finding an API during my VB days which disabled visual control-updates - can anyone confirm whether such an API (or SendMessage parm) exists?

[edit]
Found it - LockWindowUpdate. All sorted now :o)

I hadn't noticed that since I always used these functions to work with the currently selected node.

Does this work instead? I don't have any code using this currently so I can't really try it...

	
	Local Item:TVITEM = New TVITEM, pItem:Byte Ptr = Item
	Local hwndView:Int, hwndNode:Int
	
	hwndView = QueryGadget(TreeView, QUERY_HWND)
	hwndNode = QueryGadget(Node, QUERY_HWND)

	'or maybe uncomment this - not sure why it was commented out, since it appears
	'to try to do the same thing
	'hwndNode = QueryGadget(Node, 1)


I did try that, but hwndNode=QueryGadget(Node, QUERY_HWND) returns zero every time. There probably is a way to do it but I don't have enough knowledge on treeview structures to work out how. It would be extremely useful to be able to access any treeview node's data without having to select it first.