Sapero
You worked on this code on the old forums in 2005.
When I try to run it in EB now and I get a ton of errors.
Do you happen to have a copy that runs now?
$include "windows.inc"
autodefine "off"
WINDOW d1
OpenWindow d1,0,0,295,230,@caption,d1,"Advanced TreeView demo",&handler
CONTROL d1,@TREEVIEW,"Static",18,3,252,188,0x50800027|TVS_CHECKBOXES,1
UINT TreeBkColor, TvLastHitItems
INT bDragging :' drag running
UINT TVhwnd :' handle to tree
UINT hDragItem :' handle to dragged tree item
UINT hDragImageList :' handle to drag imagelist
UINT hImageList :' handle to imagelist
UINT handle[15] :' item handles
TVhwnd = GetDlgItem(d1.hwnd, 1)
AddItems()
TreeBkColor = rgb(210,210,210)
SetWindowColor d1, TreeBkColor
SendMessage d1, TVM_SETINDENT, 8, 0, 1
TreeView_SetBkColor(TVhwnd, TreeBkColor)
TreeView_SetLineColor(TVhwnd, 0)
TreeView_SetTextColor(TVhwnd, 0x8FFFFF)
TreeView_SetItemHeight(TVhwnd, 16)
'messagebox 0, hex$(TreeView_GetTextColor(TVhwnd)), ""
While hImageList=0
hImageList = ImageList_LoadImage(0, "tree.bmp", 10/*each image size*/, 2/*images*/, 0x808080/*color mask*/, IMAGE_BITMAP, LR_LOADFROMFILE|LR_LOADTRANSPARENT)
IF hImageList = 0
IF URLDownloadToFileA(0, "http://people.freenet.de/ibasic/tree.bmp", GetStartPath+"tree.bmp", 0, 0)
hImageList=1
Endif
Endif
Wend
starttimer d1, 500
'TreeView_SetImageList(TVhwnd, TVSIL_NORMAL, hImageList)
'TreeView_SetImageList(TVhwnd, TVSIL_STATE, hImageList)
'TreeView_Collapse(TVhwnd, handle[0])
TreeView_SetCheckState(TVhwnd, handle[0], 1)
TreeView_SetCheckState(TVhwnd, handle[1], 1)
TreeView_SetCheckState(TVhwnd, handle[2], 1)
TreeView_SetItemState(TVhwnd, handle[0], TVIS_BOLD, TVIS_BOLD)
TreeView_SetItemState(TVhwnd, handle[3], TVIS_BOLD, TVIS_BOLD)
TreeView_SetItemState(TVhwnd, handle[6], TVIS_BOLD, TVIS_BOLD)
WaitUntil d1.hwnd=0
ImageList_Destroy(hImageList)
'-------------------------
Sub handler
POINT pt
Select @message
Case @idcreate
CenterWindow d1
Case @idtimer
setcaption d1, "item [0] checked: "+str$(TreeView_GetCheckState(TVhwnd, handle[0]))
Case @IDCLOSEWINDOW
CloseWindow d1
Case @idlbuttonup
IF bDragging Then TVStopDraghandler()
Case @IDMOUSEMOVE
IF bDragging Then TvMoveDragImage()
Case @IDCONTROL
Select @CONTROLID
Case 1
Select @NOTIFYCODE
Case NM_CUSTOMDRAW
Return TVSubclassDrag(*<NMTVCUSTOMDRAW>@lParam)
Case TVN_BEGINDRAG
TVBeginDrag(d1.hwnd, TVhwnd, *<NMTREEVIEW>@lparam)
case @nmrclick
GetMouseCoords(d1.hwnd, pt)
contextmenu d1, pt.x, pt.y
menuitem "nix! :)", 0, 1000
endmenu
EndSelect
EndSelect
EndSelect
Return
EndSub
'-------------------------
Sub TVSubclassDrag(lParam:NMTVCUSTOMDRAW),uint
Select lParam.nmcd.dwDrawStage
Case CDDS_PREPAINT
' Need to process this case and set pResult to CDRF_NOTIFYITEMDRAW,
' otherwise parent will never receive CDDS_ITEMPREPAINT notification.
Return CDRF_NOTIFYITEMDRAW
Case CDDS_ITEMPREPAINT
Select lParam.iLevel
Case 0 :' painting all 0-level items blue
IF (lParam.nmcd.uItemState & (CDIS_FOCUS | CDIS_SELECTED))
lParam.clrText = RGB(0, 0, 0)
lParam.clrTextBk = RGB(0, 255, 0)
Else
lParam.clrText = RGB(0, 0, 255)
Endif
Return CDRF_NEWFONT
Case 1 :' painting all 1-level items red
IF (lParam.nmcd.uItemState & (CDIS_FOCUS | CDIS_SELECTED))
lParam.clrText = RGB(0, 0, 0)
lParam.clrTextBk = RGB(255, 255, 0)
Else
lParam.clrText = RGB(255, 0, 0)
Endif
Return CDRF_NEWFONT
Case 2 :' painting all 2-level items green
IF (lParam.nmcd.uItemState & (CDIS_FOCUS | CDIS_SELECTED))
lParam.clrText = RGB(0, 0, 0)
lParam.clrTextBk = RGB(0, 255, 255)
Else
lParam.clrText = RGB(255, 255, 0)
Endif
Return CDRF_NEWFONT
EndSelect
Return CDRF_NEWFONT
EndSelect
Return CDRF_DODEFAULT
EndSub
'-------------------------
Sub TVBeginDrag(parent:uint, hTree:uint, nmtv:NMTREEVIEW)
WINRECT rc
UINT dwLevel, dwIndent
TVhwnd = hTree
' get the handle to currend item
hDragItem = nmtv.itemNew.hItem
'Tell the tree-view control to create an image to use for dragging
hDragImageList = TreeView_CreateDragImage(TVhwnd, hDragItem)
'Get the bounding rectangle of the item being dragged
TreeView_GetItemRect(TVhwnd, nmtv.itemNew.hItem, rc, TRUE)
'Get the heading level and the amount that the child items are indented
dwLevel = nmtv.itemNew.lParam
dwIndent = TreeView_GetIndent(TVhwnd)
'Start the drag operation
ImageList_BeginDrag(hDragImageList, 0, 0, 0)
ImageList_DragEnter(0, 50, 50)
'direct mouse input to the parent window
bDragging = TRUE
SetCapture(parent)
Return
EndSub
'-------------------------
Sub TvMoveDragImage()
POINT pt
TVHITTESTINFO tvh
ImageList_DragLeave(0)
GetCursorPos(tvh.pt)
GetCursorPos(pt)
tvh.flags = TVHT_ONITEM
ScreenToClient(TVhwnd, tvh.pt)
TvLastHitItems = TreeView_HitTest(TVhwnd, tvh)
IF TvLastHitItems Then TreeView_SelectItem(TVhwnd, TvLastHitItems)
ImageList_DragEnter(0, pt.x, pt.y)
Return
EndSub
'-------------------------
Sub TVStopDraghandler
TVHITTESTINFO tvh
TVINSERTSTRUCT tvis
ISTRING txt[261]
bDragging = FALSE
ImageList_DragLeave(TVhwnd)
ImageList_EndDrag()
ImageList_Destroy(hDragImageList)
ReleaseCapture()
' get item handle from mouse position
GetCursorPos(tvh.pt)
ScreenToClient(TVhwnd, tvh.pt)
tvh.flags = TVHT_ONITEM
TreeView_HitTest(TVhwnd, tvh)
IF tvh.hItem and (tvh.hItem <> hDragItem)
TVcopyItem(/*source*/TVhwnd, hDragItem, /*dest*/TVhwnd, tvh.hItem, /*flags*/TVI_LAST)
TreeView_DeleteItem(TVhwnd, hDragItem)
Endif
Return
EndSub
'-------------------------
Sub TVcopyItem(tree_handle_from:uint, hItem_from:uint, tree_handle_to:uint, hItem_to:uint, flags:uint/* TVI_LAST... */)
UINT hChild, hNew
TVINSERTSTRUCT tvis
ISTRING txt[261]
IF (hItem_from = hItem_to) Then Return
IF (tree_handle_from * hItem_from * tree_handle_to * hItem_to) = 0 Then Return
' get the item
tvis.tvi.hItem = hItem_from
tvis.tvi.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_STATE | TVIF_TEXT | TVIF_PARAM
tvis.tvi.stateMask = 0xFFFF :' all TVIS_
tvis.tvi.pszText = txt
tvis.tvi.cchTextMax = 260
TreeView_GetItem(tree_handle_from, tvis.tvi)
' copy the item to new position
tvis.hParent = hItem_to
tvis.hInsertAfter = flags
hNew = TreeView_InsertItem(tree_handle_to, tvis)
' enum and move all sub/child items
hChild = TreeView_GetChild(tree_handle_from, hItem_from)
While hChild
TVcopyItem(tree_handle_from, hChild, tree_handle_to, hNew, flags)
hChild = TreeView_GetNextSibling(tree_handle_from, hChild)
Wend
Return
EndSub
'-------------------------
Sub AddItems
' UINT handle[9]
handle[0] = tvInsertItem(d1, 1, "root item 1", 0)
handle[1] = tvInsertItem(d1, 1, "subitem 1.1", handle[0])
handle[2] = tvInsertItem(d1, 1, "subitem 1.1.1", handle[1])
handle[3] = tvInsertItem(d1, 1, "root item 2", 0)
handle[4] = tvInsertItem(d1, 1, "subitem 2.1", handle[3])
handle[5] = tvInsertItem(d1, 1, "subitem 2.1.1", handle[4])
handle[6] = tvInsertItem(d1, 1, "root item 3", 0)
handle[7] = tvInsertItem(d1, 1, "subitem 3.1", handle[6])
handle[8] = tvInsertItem(d1, 1, "subitem 3.2", handle[6])
handle[9] = tvInsertItem(d1, 1, "subitem 3.3", handle[6])
handle[10] = tvInsertItem(d1, 1, "subitem 3.4", handle[6])
handle[11] = tvInsertItem(d1, 1, "subitem 3.2.1", handle[8])
handle[12] = tvInsertItem(d1, 1, "subitem 3.2.2", handle[8])
handle[13] = tvInsertItem(d1, 1, "subitem 3.2.3", handle[8])
handle[14] = tvInsertItem(d1, 1, "subitem 3.2.4", handle[8])
TreeView_Expand(TVhwnd, handle[0])
TreeView_Expand(TVhwnd, handle[1])
TreeView_Expand(TVhwnd, handle[3])
TreeView_Expand(TVhwnd, handle[4])
TreeView_Expand(TVhwnd, handle[6])
Return
EndSub
Larry
I got it working, and also updated the image on freenet server. Added a protection to prevent dropping items to its child nodes (tvIsChildOf).
The blue and red circle represents a checkbox, the red one is for 'unchecked' state. This is set by TVSIL_STATE.
Many thanks Sapero ;D
Larry
Sapero
Tried to run it and got these errors:
QuoteCompiling...
treevcopy.eba
File: commctrl.inc (367) duplicate declaration - HIMAGELIST
File: commctrl.inc (368) duplicate declaration - BOOL
File: commctrl.inc (370) duplicate declaration - int
File: commctrl.inc (371) duplicate declaration - BOOL
File: commctrl.inc (373) duplicate declaration - int
File: commctrl.inc (375) duplicate declaration - int
File: commctrl.inc (376) duplicate declaration - COLORREF
File: commctrl.inc (377) duplicate declaration - COLORREF
File: commctrl.inc (378) duplicate declaration - BOOL
File: commctrl.inc (406) duplicate declaration - BOOL
File: commctrl.inc (407) duplicate declaration - BOOL
File: commctrl.inc (408) duplicate declaration - int
File: commctrl.inc (409) duplicate declaration - BOOL
File: commctrl.inc (410) duplicate declaration - BOOL
File: commctrl.inc (411) duplicate declaration - BOOL
File: commctrl.inc (412) duplicate declaration - HICON
File: commctrl.inc (413) duplicate declaration - HIMAGELIST
File: commctrl.inc (414) duplicate declaration - HIMAGELIST
File: commctrl.inc (424) duplicate declaration - BOOL
File: commctrl.inc (425) duplicate declaration - BOOL
File: commctrl.inc (426) duplicate declaration
File: commctrl.inc (427) duplicate declaration - BOOL
File: commctrl.inc (428) duplicate declaration - BOOL
File: commctrl.inc (429) duplicate declaration - BOOL
File: commctrl.inc (430) duplicate declaration - BOOL
File: commctrl.inc (431) duplicate declaration - BOOL
File: commctrl.inc (432) duplicate declaration - HIMAGELIST
File: commctrl.inc (465) duplicate declaration - BOOL
File: commctrl.inc (466) duplicate declaration - BOOL
File: commctrl.inc (467) duplicate declaration - BOOL
File: commctrl.inc (468) duplicate declaration - HIMAGELIST
File: commctrl.inc (469) duplicate declaration - HIMAGELIST
File: C:\_EBDev\projects\treeviewdrag\treevcopy.eba (56) Warning: undeclared function 'INDEXTOSTATEIMAGEMASK'
Error(s) in compiling C:\_EBDev\projects\treeviewdrag\treevcopy.eba
Any ideas?
Larry
Oops! ::)
I still had an old controlpk.incc in the bin directory.
Now when I try to compile I just get this:
QuoteCompiling...
treevcopy.eba
File: C:\_EBDev\projects\treeviewdrag\treevcopy.eba (56) Warning: undeclared function 'INDEXTOSTATEIMAGEMASK'
C:\_EBDev\projects\treeviewdrag\treevcopy.a:519: error: symbol `INDEXTOSTATEIMAGEMASK' undefined
C:\_EBDev\projects\treeviewdrag\treevcopy.a:2299: error: phase error detected at end of assembly.
Error(s) in assembling C:\_EBDev\projects\treeviewdrag\treevcopy.a
Larry
There is updated SDK pak to download, be sure to backup your bass.inc if you have newer than 2.2.
Or just add this function:
sub INDEXTOSTATEIMAGEMASK(int i),int
return i<<12
endsub
thanks
Larry
Sapero
I was using this code of your's to try and get my bitmaps to work and I'm not having any luck.
I stripped out all the drag related code because I don't need that.
My bitmap is 160 x 60
I set itemheight to 70 to allow a little spacing between images and that works.
problem is if I use a number greater than 1/2 the width I don't det anything for a image and if I double click where it is suppose to be I get a fault message and crash.
If I set it to 80 or less that portion of the image shows and double clicking on it doesn't hurt anything.
here's the code I'm using
$include "windowssdk.inc"
$include "commctrl.inc"
autodefine "off"
WINDOW d1
OpenWindow d1,0,0,295,230,@caption,d1,"Advanced TreeView demo",&handler
CONTROL d1,@TREEVIEW,"Static",18,3,252,188,0x50800027|TVS_CHECKBOXES,1
UINT TreeBkColor, TvLastHitItems
UINT TVhwnd :' handle to tree
UINT hImageList :' handle to imagelist
UINT handle[15] :' item handles
TVhwnd = GetDlgItem(d1.hwnd, 1)
AddItems()
TreeBkColor = rgb(210,210,210)
SetWindowColor d1, TreeBkColor
SendMessage d1, TVM_SETINDENT, 8, 0, 1
SendMessageA(TVhwnd, TVM_SETBKCOLOR, 0, TreeBkColor)
SendMessageA(TVhwnd, TVM_SETLINECOLOR, 0, 0)
SendMessageA(TVhwnd, TVM_SETTEXTCOLOR, 0, 0x0000FF)
SendMessageA(TVhwnd, TVM_SETITEMHEIGHT, 70, 0)
'messagebox 0, hex$(TreeView_GetTextColor(TVhwnd)), ""
While hImageList=0
'hImageList = ImageList_LoadImage(0, GetStartPath+"tree.bmp", 10/*each image size*/, 2/*images*/, 0x808080/*color mask*/, IMAGE_BITMAP, LR_LOADFROMFILE|LR_LOADTRANSPARENT)
hImageList = ImageList_LoadImage(0, GetStartPath+"0025.bmp", 80/*each image size*/, 10/*images*/, 0x000000/*color mask*/, IMAGE_BITMAP, LR_LOADFROMFILE|LR_MONOCHROME)
IF hImageList = 0
IF URLDownloadToFileA(0, "http://people.freenet.de/ibasic/tree.bmp", GetStartPath+"tree.bmp", 0, 0)
hImageList=1
Endif
Endif
Wend
starttimer d1, 500
'SendMessageA(TVhwnd, TVM_SETIMAGELIST, TVSIL_NORMAL, hImageList)
SendMessageA(TVhwnd, TVM_SETIMAGELIST, TVSIL_STATE, hImageList)
'TreeView_Collapse(TVhwnd, handle[0])
TreeView_SetCheckState(TVhwnd, handle[0], 1)
TreeView_SetCheckState(TVhwnd, handle[1], 1)
TreeView_SetCheckState(TVhwnd, handle[2], 1)
TreeView_SetCheckState(TVhwnd, handle[3], 1)
TreeView_SetCheckState(TVhwnd, handle[4], 1)
TreeView_SetCheckState(TVhwnd, handle[5], 1)
TreeView_SetItemState(TVhwnd, handle[0], TVIS_BOLD, TVIS_BOLD)
TreeView_SetItemState(TVhwnd, handle[1], TVIS_BOLD, TVIS_BOLD)
TreeView_SetItemState(TVhwnd, handle[2], TVIS_BOLD, TVIS_BOLD)
TreeView_SetItemState(TVhwnd, handle[3], TVIS_BOLD, TVIS_BOLD)
TreeView_SetItemState(TVhwnd, handle[4], TVIS_BOLD, TVIS_BOLD)
TreeView_SetItemState(TVhwnd, handle[5], TVIS_BOLD, TVIS_BOLD)
WaitUntil d1.hwnd=0
ImageList_Destroy(hImageList)
sub TreeView_SetItemState(HWND hwndTV,HTREEITEM hItem,UINT state,UINT stateMask),UINT
TVITEM tvi
tvi.mask = TVIF_STATE
tvi.hItem = hItem
tvi.state = state
tvi.stateMask = stateMask
return SendMessageA(hwndTV, TVM_SETITEM, 0, &tvi)
endsub
sub TreeView_SetCheckState(HWND hwndTV,HTREEITEM hItem,BOOL fCheck),UINT
'return TreeView_SetItemState(hwndTV, hItem, INDEXTOSTATEIMAGEMASK(IIF(fCheck,2,1)), TVIS_STATEIMAGEMASK)
return TreeView_SetItemState(hwndTV, hItem, INDEXTOSTATEIMAGEMASK(IIF(fCheck,1,1)), TVIS_STATEIMAGEMASK)
endsub
sub TreeView_GetCheckState(HWND hwndTV, HTREEITEM hItem),UINT
return (SendMessageA(hwndTV, TVM_GETITEMSTATE, hItem, TVIS_STATEIMAGEMASK) >> 12) -1
endsub
'-------------------------
Sub handler
POINT pt
Select @message
Case @idcreate
CenterWindow d1
Case @idtimer
setcaption d1, "item [0] checked: "+str$(TreeView_GetCheckState(TVhwnd, handle[0]))
Case @IDCLOSEWINDOW
CloseWindow d1
Case @IDCONTROL
Select @CONTROLID
Case 1
Select @NOTIFYCODE
case @nmrclick
GetCursorPos(&pt)
ScreenToCLient(d1.hwnd, &pt)
contextmenu d1, pt.x, pt.y
menuitem "nix! :)", 0, 1000
endmenu
EndSelect
EndSelect
EndSelect
Return
EndSub
'-------------------------
'-------------------------
'-------------------------
Sub AddItems
' UINT handle[9]
handle[0] = tvInsertItem(d1, 1, "root item 1", 0)
handle[1] = tvInsertItem(d1, 1, "root item 2", 0)
handle[2] = tvInsertItem(d1, 1, "root item 3", 0)
handle[3] = tvInsertItem(d1, 1, "root item 4", 0)
handle[4] = tvInsertItem(d1, 1, "root item 5", 0)
handle[5] = tvInsertItem(d1, 1, "root item 6", 0)
' SendMessageA(TVhwnd, TVM_EXPAND, TVE_EXPAND, handle[0])
'SendMessageA(TVhwnd, TVM_EXPAND, TVE_EXPAND, handle[1])
'SendMessageA(TVhwnd, TVM_EXPAND, TVE_EXPAND, handle[2])
Return
EndSub
Attached are my bitmap and the best I can get it to display.
Larry
I'm not sure why it crashes, but it does in comctl32.dll. It loads the number of images from imagelist and divides something by zero (calculated).
Probably the height of state-image must be equal or greater than width, or width and height cannot exceed 80 pixels.
Maybe better you use owner drawn listbox, or implement your own control.
By the way, the 10 in ImageList_LoadImage is invalid, you cannot load 10 * 80px images from a 160px bitmap.
All the Treeview_* functions are already defined in commctrl.inc, but the TreeView_SetCheckState macro has a hard bug (fixed today 2 April). I have uploaded the new headers.
I decided that since it was showing only 1/2 of my image that I would reduce my image by 1/2.
To my surprise it only displayed 1/2 of the smaller image.
Maybe everyone else knew this but me.
iit appears that since this is suppose to be a state image it expects one 1/2 of the image to be the set image and the other half is the reset image.
I took my image and stretched the canvas so it had another image space and it displayed the one I wanted just like I wanted.
Larry