en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en nl en en en en en en en en en en en en nl en en en tr en en en en en en en en en en nl en en en en en en en de en de en en en en en fr en da en en en en en en en nl en en en en en en en en en en en nl en en en en en en en en en en en en fr en da en en en en en en en nl en en en en en en en en en en nl vi en en en en en en en fr en da en en en en en en en nl en en en en en en en en en en nl fr en en en en en en en en en en en en en en en en en en en en en en en en nl en en en en en en en en en en fr en da en en en en en en en nl en en en en en en en en en en en en en nl en en en en en en en en en en en en en en en en nl en en en en en en en en en en en de en en en fr en en en en en en en en en pt en en en en en en
By logging into your account, you agree to our Privacy Policy, personal data processing and storage practices as described therein.
Forgot password or user name?
Search in titles only Search in PowerBASIC for Windows only
You are not logged in. You can browse in the PowerBASIC Community, but you must click Login (top right) before you can post. If this is your first visit, check out the FAQ or Sign Up.
Detecting checkbox flip in treeview
All Time Today Last Week Last Month
All Discussions only Photos only Videos only Links only Polls only Events only
I understand that when a checkbox (or anything) is clicked inside a treeview, I will get a %WM_NOTIFY, and that if I grab CBLPARAM.idfrom it will match the handle of my treeview, and that if I look at CBLPARAM.hdr.Code, it will match %NM_CLICK... but I'm sort of lost at that point in getting the handle of the item that was clicked on.
I assumed CBLPARAM.itemNew.hItem or something like that, but no luck.
What I'm trying to do is detect when a checkbox has been flipped on a treeview. Previously I was just scanning the entire thing for changes every time there was a click, but there has to be an easier way to do it.
IF CB.NMID = %IDC_CITIESTREE THEN
IF CB.NMCODE = %NM_CLICK THEN
...if we get here, the treeview IDC_CITIESTREE has been clicked on, but how do I know which of the elements has been clicked on?
Join Date: Aug 1998
12 Nov 2009, 01:35 PM
Do you want to know if it has been clicked, or do you want to know if that click has changed the selected item? (This came up here not too long ago).
Depending on which one you want, you process WM_NOTIFY/NM_CLICK or WM_NOTIFY/TVN_SELCHANGED ( or TVN_SELCHANGING if you want to disallow the selection of this item)
FWIW, you get TVN_SELCHANGED when the user uses the keyboard as well as the mouse to change selection.
If it's really "click" you want, you have to figure out where the click occurred, then use the Treeview_HitTest function to figure out where on which item (if any) the cursor was when the mouse was clicked. .. then you can use Treeview_getCheckState to query the check status.
(I can't find a TVN_ITEMCHANGED which handles state changes! There must be one somewhere!)
THis will be about ten lines of code. You will probably want to put it into a reusable function such as "Treeview_WhereWasClick" so you only have to do it ONCE.
I am sure the code is posted here, but not in the source code forum.
Last edited by Michael Mattias; 12 Nov 2009, 01:40 PM.
Port Washington WI USA
Join Date: Nov 2009
12 Nov 2009, 03:19 PM
Thanks -- I want to know which one was clicked on. So it sounds like there's no simple one-call return function... I'm surprised, I would have though there would be something that returned a handle to the item that was clicked on, and some of the data structures implied that was what they could do.
I have another Treeview question while we're at it -- if I want to select all or deselect all (of the the checkboxes), how can I do that in bulk, without flicker issues? Can I temporarily turn off redrawing and then make all the changes and then turn it back on.
Join Date: Aug 1998
12 Nov 2009, 04:55 PM
So it sounds like there's no simple one-call return function... I'm surprised, I would have though there would be something that returned a handle to the item that was clicked
There will be - after you write it. Here's a start:
FUNCTION OnWhichItemDidClickHappen (hTV AS LONG, NMH NMHDR) AS LONG ' Return: hItem on which click occurred, or null if click occurred ' on the control BUT NOT ON AN ITEM AND YES THIS HAPPENS END FUNCTION
BTW, make sure you want CLICKS and not "CHANGE OF SELECTION BY EITHER CLICK OR KEYBOARD." Last thing you want is for the user to complain about 'keys don't work' (and you KNOW that is how it will come back to you!)
Also, "selected" with a treeview does NOT mean "the checkbox is checked". You can have only one selection at a time, but many items may be checked!
(I know someone posted a tree view with check boxes demo here. Try a search on "TVS_CHECKBOXES" and you should find it, since that style had to be included)
Port Washington WI USA
Join Date: Nov 2009
12 Nov 2009, 05:26 PM
Hahaha... I can't tell if you're messing with me or if you're giving me useful advice or both. It's the guts of that function that I'm stuck on, not its declaration.
Join Date: Aug 1998
12 Nov 2009, 05:37 PM
I don't mess with people. All statements above are feither fact as I know it or my honest "best guess" at what you should do next. If my facts are shown to be wrong, I will promptly acknowledge and correct.
However, I am in no position to judge if the suggestions or advice I offer are useful.
>It's the guts of that function that I'm stuck on
I wasn't about to pre-empt the fun you will have creating it. That would not be nice at all, would it?
Port Washington WI USA
Join Date: Nov 2009
12 Nov 2009, 05:44 PM
Thanks, admittedly I am under no particular deadline so I have been having fun slowly figuring it all out. I do console apps 99% of the time, so I'm still fairly unfamiliar with GUI programming.
Join Date: Nov 2004
12 Nov 2009, 05:51 PM
PB will give you the rudiments of the event, there's a lot more buried in the structure which is passed to the window via the NMHDR Structure, AKA in PB it's CB.NMHDR, and that header is common across a bunch of notification systems, for the treeview control, you need to:
LOCAL pnmtv AS NM_TREEVIEW POINTER
and there's something to note here, the CB.NMHDR is a pointer, CB.NMCODE, CB.NMHWND, & CB.NMID are all derived from the structure, alias:
TYPE NMHDR hwndFrom AS DWORD idfrom AS DWORD CODE AS LONG ' used for messages, so needs to be LONG, not DWORD... END TYPE
And when you look at NM_TREEVIEW:
TYPE NM_TREEVIEW hdr AS NMHDR action AS DWORD itemOld AS TV_ITEM itemNew AS TV_ITEM ptDrag AS POINTAPI END TYPE
See? And if you're following along;
CASE %WM_NOTIFY IF ISTRUE isLoading THEN EXIT FUNCTION SELECT CASE CB.NMID CASE %IDTV_FOXTREE IF CB.NMCODE = %TVN_SELCHANGED THEN ' make image here SELECT CASE CB.NMID CASE %IDTV_FOXTREE DisplaySelectedImage CB.HNDL, CB.NMID, CB.NMHDR
My code sets up a function call at this point, but in the function, I then use the above pointer declaration to gain access to the itemOld and itemNew elements of the structure:
SUB DisplaySelectedImage(hDialog AS DWORD, idControl AS DWORD, pnmhdr AS DWORD) LOCAL pnmtv AS NM_TREEVIEW POINTER LOCAL pitem AS TV_ITEM LOCAL BumpX AS LONG LOCAL hControl, hBitmap AS DWORD LOCAL KeyControl AS INTEGER KeyControl = (GetKeyState(%VK_CONTROL) AND &H8000) IF ISTRUE SetCurrentShape(hDialog, idControl) THEN pnmtv = pnmhdr IF @pnmtv.action = %TVC_BYMOUSE THEN CONTROL HANDLE hDialog, %IDTV_FOXTREE TO hControl IF (ISTRUE @pnmtv.itemOld.hItem) AND (ISFALSE KeyControl) THEN pitem.hItem = @pnmtv.itemOld.hItem pitem.mask = %TVIF_STATE pitem.stateMask = %TVIS_BOLD BumpX = TreeView_GetItem(hControl, pitem) pitem.state = pitem.state AND (NOT %TVIS_BOLD) BumpX = TreeView_SetItem(hControl, pitem) END IF IF ISTRUE @pnmtv.itemNew.hItem THEN pitem.hItem = @pnmtv.itemNew.hItem pitem.mask = %TVIF_STATE pitem.stateMask = %TVIS_BOLD BumpX = TreeView_GetItem(hControl, pitem) pitem.state = pitem.state OR %TVIS_BOLD BumpX = TreeView_SetItem(hControl, pitem) END IF END IF hBitmap = MakeFshBitmap(CurrentShape, CurrentFrame, Fox) CONTROL SEND hDialog, %idf_imagedisplay, %UM_SETIMAGE, _ hBitmap, Fox.ComboPosition(CurrentShape, CurrentFrame) END IF END SUB
Furcadia, an interesting online MMORPG in which you can create and program your own content.
Join Date: Aug 1998
12 Nov 2009, 05:52 PM
I think what you are going to need to do here is two things...
1. On click, check to see of the click was an item or not
2. On   (use WM_NOTIFY/TVN_KEYDOWN) check to see what item was currently selected.
I think the checkbox status will be toggled automatically on either, meaning you really don't have to do anything vis-a-vis toggling the check state.
But we really don't know what it is you want to do when the user clicks (or selects?)
Port Washington WI USA
Join Date: Nov 2004
12 Nov 2009, 05:54 PM
Originally posted by Michael Mattias View Post
I think the checkbox status will be toggled automatically on either, meaning you really don't have to do anything vis-a-vis toggling the check state.
Furcadia, an interesting online MMORPG in which you can create and program your own content.
Join Date: Jan 2003
13 Nov 2009, 11:57 AM
Well, my first google search using the phrase "treeview using tvs_checkboxes" return this link. It says that when a user clicks on the state icon that an NM_CLICK notification is sent and the TVM_HITTEST message will return TVHT_ONITEMSTATEICON. Unfortunately, the treeview doesn't actually change the state until after the NM_CLICK notification is sent so you can't just check the state on an NM_CLICK.
His suggestion is to send a custom message to your dialog procedure when you get an NM_CLICK and TVM_HITTEST returns TVHT_ONITEMSTATEICON.
Here is my conversion of the code at the above linked converted to PB:
' make sure you have these includes #INCLUDE "Win32API.inc" #INCLUDE "CommCtrl.inc" ' add this equate to the start of your program %UM_CHECKSTATECHANGE = %WM_USER + 100 ' add these variable declarations in your dialog procedure LOCAL dPos AS DWORD LOCAL tHTI AS TVHITTESTINFO ' add the following case to your SELECT CASE CB.MSG CASE %WM_NOTIFY SELECT CASE CB.NMID CASE %IDC_TREEVIEW1 IF CB.NMCODE = %NM_CLICK THEN dPos = GetMessagePos tHTI.pt.x = LO(WORD, dPos) tHTI.pt.y = HI(WORD, dPos) MapWindowPoints %HWND_DESKTOP, CB.NMHWND, tHTI.pt, 1 TreeView_HitTest CB.NMHWND, tHTI IF tHTI.flags AND %TVHT_ONITEMSTATEICON THEN PostMessage CB.HNDL, %UM_CHECKSTATECHANGE, 0, tHTI.hItem END IF END IF END SELECT CASE %UM_CHECKSTATECHANGE hItemChanged = CB.LPARAM ' handle of the item whose state icon was clicked ' you can now get the state of the item
Hopefully I ddin't screw anything up as I didn't test this code.
Join Date: Feb 2001
13 Nov 2009, 07:55 PM
send a custom message to your dialog procedure when you get an NM_CLICK and TVM_HITTEST returns TVHT_ONITEMSTATEICON.
There's a good example of this technique in the Three State Checkbox Treeview example posted in the Source Code forum by Steve Mc Gregor..
Actually that example addresses just about all the questions raised by this thread
Copyright © 1998-2022 PowerBASIC Tools, LLC - All Rights Reserved.
Powered by vBulletin® Version 5.7.0
Copyright © 2022 vBulletin Solutions, Inc. All rights reserved.
All times are GMT-5. This page was generated at 10:36 PM.
We process personal data about users of our site, through the use of cookies and other technologies, to deliver our services, and to analyze site activity. For additional details, refer to our Privacy Policy.
By clicking "I AGREE" below, you agree to our Privacy Policy and our personal data processing and cookie practices as described therein. You also acknowledge that this forum may be hosted outside your country and you consent to the collection, storage, and processing of your data in the country where this forum is hosted.