Can more than one treeviewnode in a tree be selected at once?
BlitzPlus Forums/BlitzPlus Programming/Can more than one treeviewnode in a tree be selected at once?
| ||
Is it possible to select multiple treeview nodes at the same time? I don't think B+ supports this, but can it be done with a workaround? What about list boxes? Can more than one of these items be selected at once? |
| ||
There's got to be a way to use SendMessage() to do it. Anyone know what the parameters are? |
| ||
Halo, take a look at the docs here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/listview/listview.asp Click (in the left section) List-View Controls Reference -- the messages (use SendMessage and the QueryObject window handle), constants, etc, are there. On a quick glance, I get the impression Blitz's 'ListBoxes' have the 'single-selection only' flag on (LVS_SINGLESEL); it *might* be possible to remove this via SetWindowLong... There's similar stuff for TreeViews here, though I don't think you can select more than one item ever in these... http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/treeview/reflist.asp |
| ||
Thanks man. I tried this, but don't see any difference. The listview is the one that really matters. I am starting a new project right now. Getting this to work is fundamental, and I am losing time and money as long as it doesn't work. Any ideas? I found something somewhere saying that constant equals $0004. w=640 h=480 Global window=CreateWindow(PROGRAMTITLE,(ClientWidth(Desktop())-w)/2,(ClientHeight(Desktop())-h)/2,w,h,0) list=CreateListBox(x,y,ClientWidth(window),ClientHeight(window)-y,window) SetGadgetLayout list,1,1,1,1 For n=1 To 100 AddGadgetItem list,"item "+n Next hwnd=QueryObject(list,1) SetWindowLong hwnd,$0004,1 Repeat Select WaitEvent() Case $803 End End Select Forever |
| ||
hmmm...GetWindowLong(hwnd,$0004) returns 0, no matter what I do.w=640 h=480 Global window=CreateWindow(PROGRAMTITLE,(ClientWidth(Desktop())-w)/2,(ClientHeight(Desktop())-h)/2,w,h,0) list=CreateListBox(x,y,ClientWidth(window),ClientHeight(window)-y,window) hwnd=QueryObject(list,1) SetWindowLong(hwnd,4,1) RuntimeError GetWindowLong(hwnd,4) |
| ||
I had the same problem a few months ago and it set me back for a long time on my current project. unfortunately, it boiled down to me writing my own treeview system and treeview renderer (which renders the tvw to a canvas). I highly suggest this method as you have full control over everything - currently mine supports color schemes, Icons and multiple selections. and it is really fast - rendering takes around 0.05 secs. Unfortunately I'm not quite ready to release the source to this as it is the key ingredient to my current project and it is partially intertwined with my internal engine. However, once my project is finished I do plan on cleaning up the tvw system and making it more general-purpose. Just to give you an idea of the great quality you can get using this method, check out the screenshot below |
| ||
I tried creating a grid with editable cells, and found that B+ had no real easy way of doing this. The LIST control is sadly lacking, and I would have thought by now this would have been addressed. Sadly B+ has not moved forward at all, since its initial release. My solution was to buy PowerBasic, but I would have preferred using B+ :( |
| ||
Well, since SetWindowLong is having no effect on GetWindowLong(), it appears that there is no way to alter the gadget. The treeview doesn't matter so much, but I HAVE to be able to select multiple items on the listview. That's pretty sad, because it means I can't use BlitzPlus for this project, just because of one little technical windows thing. It would have been easy, because I have a whole 3D engine and stuff set up from the CShop code. If I use PureBasic, it will take two or three times as long to finish. :( |
| ||
The reason it's not working is because you need it set at -16 not 4. (GWL_STYLE=-16) This should sort out your woes, have fun :) |
| ||
Thanks, but that just freezes the gadget. |
| ||
Ok, this is all you should need to set for multi-select listview. SetWindowLong hWnd,-16,$40000000 or $10000000 or MYLBS Where MYLBS is a combination of what you need below: Const LBS_DISABLENOSCROLL=4096 Const LBS_EXTENDEDSEL=$800 Const LBS_HASSTRINGS=64 Const LBS_MULTICOLUMN=512 Const LBS_MULTIPLESEL=8 Const LBS_NODATA=$2000 Const LBS_NOINTEGRALHEIGHT=256 Const LBS_NOREDRAW=4 Const LBS_NOSEL=$4000 Const LBS_NOTIFY=1 Const LBS_OWNERDRAWFIXED=16 Const LBS_OWNERDRAWVARIABLE=32 Const LBS_SORT=2 Const LBS_STANDARD=$a00003 Const LBS_USETABSTOPS=128 Const LBS_WANTKEYBOARDINPUT=$400 $4000000= Child Window $1000000= Visable Hope this helps |
| ||
My bad, the above is for listboxes... DOH! I can't find the LVS_ constants atm, I'll dig deeper. |
| ||
Here you go, these are the LVS_ constantsConst LVS_ICON=$0 Const LVS_REPORT=$1 Const LVS_SMALLICON=$2 Const LVS_LIST=$3 Const LVS_TYPEMASK=$3 Const LVS_SINGLESEL=$4 Const LVS_SHOWSELALWAYS=$8 Const LVS_SORTASCENDING=$10 Const LVS_SORTDESCENDING=$20 Const LVS_SHAREIMAGELISTS=$40 Const LVS_NOLABELWRAP=$80 Const LVS_AUTOARRANGE=$100 Const LVS_EDITLABELS=$200 Const LVS_OWNERDATA=$1000 Const LVS_NOSCROLL=$2000 Const LVS_TYPESTYLEMASK=$fc00 Const LVS_ALIGNTOP=$0 Const LVS_ALIGNLEFT=$800 Const LVS_ALIGNMASK=$c00 Const LVS_OWNERDRAWFIXED=$400 Const LVS_NOCOLUMNHEADER=$4000 Const LVS_NOSORTHEADER=$8000 |
| ||
We're on the right track. Check this out! You can make a Windows Explorer-type display:w=640 h=480 Global window=CreateWindow(PROGRAMTITLE,(ClientWidth(Desktop())-w)/2,(ClientHeight(Desktop())-h)/2,w,h,0) list=CreateListBox(x,y,ClientWidth(window),ClientHeight(window)-y,window) SetGadgetLayout list,1,1,1,1 For n=1 To 100 AddGadgetItem list,"item "+n Next hwnd=QueryObject(list,1) SetWindowLong hwnd,-16,$40000000 Or $10000000 Or $4 Repeat Select WaitEvent() Case $803 End End Select Forever |
| ||
Sweet! I got it. Thank you thank you thank you!hwnd=QueryObject(list,1) flags=GetWindowLong(hwnd,-16) SetWindowLong hwnd,-16,flags+LVS_SINGLESEL Now I need to figure out how to check if an item is selected. |
| ||
Anytime, got it the same time as you, lol See Below.. |
| ||
Anyone know what LVM_SETITEMSTATE equals? It's something like 0x1000+43, whatever that means. Also, you need to use LVS_SHOWSELALWAYS when doing this. |
| ||
Have fun with this :) not sure if it's what you need.Const PROGRAMTITLE$="Testing Listview" ; Window Style Constants Const WS_BORDER=$800000 Const WS_CAPTION=$c00000 Const WS_CHILD=$40000000 Const WS_CHILDWINDOW=$40000000 Const WS_CLIPCHILDREN=$2000000 Const WS_CLIPSIBLINGS=$4000000 Const WS_DISABLED=$8000000 Const WS_DLGFRAME=$400000 Const WS_GROUP=$20000 Const WS_HSCROLL=$100000 Const WS_ICONIC=$20000000 Const WS_MAXIMIZE=$1000000 Const WS_MAXIMIZEBOX=$10000 Const WS_MINIMIZE=$20000000 Const WS_MINIMIZEBOX=$20000 Const WS_OVERLAPPED=0 Const WS_OVERLAPPEDWINDOW=$cf0000 Const WS_POPUP=$80000000 Const WS_POPUPWINDOW=$80880000 Const WS_SIZEBOX=$40000 Const WS_SYSMENU=$80000 Const WS_TABSTOP=$10000 Const WS_THICKFRAME=$40000 Const WS_TILED=0 Const WS_TILEDWINDOW=$cf0000 Const WS_VISIBLE=$10000000 Const WS_VSCROLL=$200000 ; Listview Style Constants Const LVS_ICON=$0 Const LVS_REPORT=$1 Const LVS_SMALLICON=$2 Const LVS_LIST=$3 Const LVS_TYPEMASK=$3 Const LVS_SINGLESEL=$4 Const LVS_SHOWSELALWAYS=$8 Const LVS_SORTASCENDING=$10 Const LVS_SORTDESCENDING=$20 Const LVS_SHAREIMAGELISTS=$40 Const LVS_NOLABELWRAP=$80 Const LVS_AUTOARRANGE=$100 Const LVS_EDITLABELS=$200 Const LVS_OWNERDATA=$1000 Const LVS_NOSCROLL=$2000 Const LVS_TYPESTYLEMASK=$fc00 Const LVS_ALIGNTOP=$0 Const LVS_ALIGNLEFT=$800 Const LVS_ALIGNMASK=$c00 Const LVS_OWNERDRAWFIXED=$400 Const LVS_NOCOLUMNHEADER=$4000 Const LVS_NOSORTHEADER=$8000 Const GWL_STYLE=-16 Type Item Field Mask Field Index Field SubIndex Field State Field stateMask Field ItemText$ Field MaxLen Field Icon Field lParam End Type w=640 h=480 Global window=CreateWindow(PROGRAMTITLE,(ClientWidth(Desktop())-w)/2,(ClientHeight(Desktop())-h)/2,w,h,Desktop(),9) Global List=CreateListBox(x,y,ClientWidth(window)/2,ClientHeight(window)-y,window) Global DispList=CreateListBox(GadgetWidth(List),y,GadgetWidth(List),GadgetHeight(List),window) SetGadgetLayout list,1,1,1,1 For n=0 To 99 AddGadgetItem list,"item "+n Next hwnd=QueryObject(list,1) PREVAL=GetWindowLong(hwnd,GWL_STYLE) SetWindowLong hwnd,GWL_STYLE,PREVAL-LVS_SINGLESEL Repeat Select WaitEvent() Case $401 Select EventSource() Case List FindSelected(hwnd) End Select Case $803 End End Select Forever Function FindSelected(hWND) CItem.Item=New Item Pointer=Int(CItem)+20 ClearGadgetItems DispList For t=0 To 99 CItem\Index=t CItem\SubIndex=0 CItem\Mask=8 CItem\StateMask=2 Suc=SendMessage(hWND,$1000+5,0,Pointer) If Suc If CItem\State AddGadgetItem DispList,GadgetItemText(List,t) EndIf EndIf Next Delete CItem End Function |
| ||
Halo, sorry for the delay in getting back to this one. It's LVM_FIRST + 43, ie. you just need to know what LVM_FIRST is ($1000) and add 43. |
| ||
BTW If you can't find a constant, just stick 'const THIS_CONSTANT' into Google and you'll usually find it. |
| ||
Here's the function for checking a single item, or just use the batch checking in the code above.Function IsItemSelected(ListView,Index) ; ListView: A ListBox gadget ; Index: Item in the ListBox to check hWND=QueryObject(ListView,1) CItem.Item=New Item Pointer=Int(CItem)+20 CItem\Index=t CItem\SubIndex=0 CItem\Mask=8 CItem\StateMask=2 SendMessage hWND,$1000+5,0,Pointer State=CItem\State Delete CItem Return State End Function |
| ||
I haven't tried this yet, but a 'cleaner' way to check for multiple selections looks to be:Repeat item = SendMessage (listview, LVM_GETNEXTITEM, -1, LVNI_SELECTED) Until item = -1 ; No more selected items |
| ||
Yup, it should work fine. Obviously by replacing -1 with a marker being the last found item. :) |
| ||
This works (and remember you can also Ctrl-select multiple groups). The only problem is that if you click and drag in the blank area right at the start, without selecting any items, it selects them all! (Maybe you can just pre-select the first item to kick things off.) And, yes, Snarty -- that had me stumped for a little while... :) w = 640 h = 480 window = CreateWindow ("Multiple listview item selection", (ClientWidth (Desktop ()) - w) / 2, (ClientHeight (Desktop ()) - h) / 2, w, h, 0) list = CreateListBox (0, 0, ClientWidth (window), ClientHeight (window) - 25, window) SetGadgetLayout list, 1, 1, 1, 1 For n = 0 To 99 AddGadgetItem list, "item " + n Next button = CreateButton ("Click for result", 0, ClientHeight (window) - 25, ClientWidth (window), 23, window) hwnd = QueryObject (list, 1) flags = GetWindowLong (hwnd, -16) SetWindowLong hwnd, -16, flags + $4 Const LVM_FIRST = $1000 Const LVNI_SELECTED = $2 Const LVM_GETNEXTITEM = LVM_FIRST + 12 Const LVM_SETSELECTIONMARK = LVM_FIRST + 67 Repeat Select WaitEvent() Case $803 End Case $401 If EventSource () = button m$ = "" ; For dialog box string... item = -1 ; Start checking from the first item (0)... Repeat ; Note the 'item' in the parameters -- we search *from* item each time round... item = SendMessage (hwnd, LVM_GETNEXTITEM, item, LVNI_SELECTED) If item <> -1 m$ = m$ + "Item: " + item + Chr (10) EndIf Until item = -1 ; No more selected items Notify m$ EndIf End Select Forever |
| ||
You guys rock. This is pretty useful knowledge for BlitzPlus, in general. |
| ||
Black Box - just as big. You can't do that and '404' us! |
| ||
Hey, is there a way to NOT alphabetize/sort the lists? ...ah, here it is: flags=GetWindowLong(hwnd,-16)-LVS_SORTASCENDING |
| ||
Just take a good look through those docs for sending messages and setting up the listview (ie. SetWindowLong), and you'll cover most complaints you might think you have! |
| ||
Hmmmm...any idea how to select or deselect an item? I tried "SendMessage hwnd,LVM_SETITEMSTATE,item,state" but it didn't do anything, Many thanks. |
| ||
I got a similar result when trying to pre-select the first item (I used LVM_SETSELECTIONMARK, though it's not clear if this actually means the selection box thing). I even tried activating the listview afterwards (via SetActiveWindow) in case it was related to whether selected items are still shown as selected when the listview doesn't have focus (adding LVS_SHOWSELALWAYS to the window style flags should do this BTW)... Short answer: I couldn't figure it out. Did you create the actual 'LVITEM' structure for that 'state' parameter BTW? |
| ||
No, I just did like 0 and 1. |
| ||
Here's one way. This will clear the list, then you just use the Blitz command to select the gadget items that should be selected: hwnd=QueryObject(list,1) flags=GetWindowLong(hwnd,-16) SetWindowLong hwnd,-16,flags-LVS_SINGLESEL SelectGadgetItem list,0 SetWindowLong hwnd,-16,flags How about making it so the list doesn't scroll to the bottom of the selection? I find that extremely annoying! |
| ||
I got better results by adding a gadget at the end, selecting it, and deleting it. However, this causes the list to scroll to the very end. Anyone know how to move the list, or set it so it doesn't auto-scroll? NOSCROLL just turns off the ability to scroll at all! |
| ||
You need to use the Type access like in my example way up there ^^ |
| ||
Here ya go. This works really well. This concludes my problem. Thanks, both of ya: Function SelectListViewItem(gadget,index,state=1) hWND=QueryObject(gadget,1) CItem.Item=New Item Pointer=Int(CItem)+20 CItem\Index=index CItem\SubIndex=0 CItem\Mask=8 CItem\StateMask=2 CItem\State=state*2 SendMessage hWND,$1000+43,index,Pointer Delete CItem End Function |
| ||
Bollix... screwed-up post. |
| ||
Good work... I can't believe I forgot about this though! you just use the Blitz command to select the gadget items that should be selected Doh! |
| ||
Yeah, but doing that scrolls the list, which I don't want. You're better off using the func I posted. |
| ||
@Halo Is there any chance that you would share this code with the community? thanks |