Thread: Trapping for checkbox events in CTreeCtrl's

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Trapping for checkbox events in CTreeCtrl's

    I found an article on MSDN about this and was wondering if any of you know of a better way.

    I have a CTreeCtrl with checkboxes for each node. The idea is to trap for the checkbox click event. MSDN makes it sound as if I must trap for this in the main message handler for the window. They show code that traps the WM_NOTIFY message, hit tests the mouse position and verifies the message came from the tree control. Then they test the flags of the TVHITTESTINFO structure to see if the TVHT_ONITEMSTATEICON bit is set. Once it is they post a user defined message to the window indicating a click on the checkbox. The window then has code to handle the user message and acts accordingly.

    What a mess eh?

    Is there a better way? Based on the pure Win32 example from MS I will have quite a bit of work to do in order to get this to work in MFC. I would have to make use of PreTranslateMessage to trap for the WM_NOTIFY and then verify the message came from my tree control. I would then need code in the same function to then call the handler for the user defined message. I've attached a screenshot of my app so you can understand what I'm using this control for. I used to use a simple list box but checking which layers are visible and which ones are not seems a lot more intuitive than a simple list of the layers. Ideally the check event would enable or disable the desired layer in my view on the right.

    http://support.microsoft.com/kb/261289/en
    Last edited by VirtualAce; 03-12-2011 at 11:41 AM.

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    I do this with Listviews not Treeviews but the principal should be the same....

    Code:
    //is a WM_NOTIFY handler in the message map
    ON_NOTIFY(LVN_ITEMCHANGED, IDC_EVENTLIST, OnLvnItemchangedEventlist)
    
    //the handler
    void EventLinker::OnLvnItemchangedEventlist(NMHDR *pNMHDR, LRESULT *pResult)
    {
    	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    	*pResult = 0;
    
    	if (pNMListView->uOldState == 0 && pNMListView->uNewState == 0)
    		return;	// No change
    
    	BOOL bPrevState = (BOOL)(((pNMListView->uOldState & LVIS_STATEIMAGEMASK)>>12)-1);   // Old check box state
    	if (bPrevState < 0)	// On startup there's no previous state 
    		bPrevState = 0; // so assign as false (unchecked)
    
    	// New check box state
    	BOOL bChecked=(BOOL)(((pNMListView->uNewState & LVIS_STATEIMAGEMASK)>>12)-1);
    	if (bChecked < 0) // On non-checkbox notifications assume false
    		bChecked = 0;
    
    	if (bPrevState == bChecked) // No change in check box
    		return;
    
    	//else remember a value changed for the save state method
    	m_iChanged=true;
    
    	*pResult = 0;
    }
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Thanks.

    I got it to work yesterday using the samples from MSDN and then found that simply testing the flags in the header passed to OnNMClickTree() and testing against TVHT_ONITEMSTATEICON works just as well.

    But you are correct in that list controls and tree controls are identical in underlying operation. In fact you can use LVNI_SELECTED with a tree control when that is specifically for a list control.

    I was trying to derive the index of the currently selected item by using GetNextItem(0,LVNI_SELECTED) but it was not working. So now I'm setting the item data in the node using SetItemData() and using a structure which contains the index of the item. Since all of my items are root items and do not have any child items I set the index member of the structure to CTreeCtrl::GetItemCount(). It works exactly as I had hoped.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Events
    By Dae in forum C++ Programming
    Replies: 0
    Last Post: 07-01-2009, 03:54 AM
  2. Persistence of network events
    By Hunter2 in forum Networking/Device Communication
    Replies: 0
    Last Post: 10-02-2004, 08:38 PM
  3. Loading cursors on events
    By cfrost in forum C++ Programming
    Replies: 1
    Last Post: 05-13-2004, 09:07 PM
  4. seismic events program
    By santaclaus in forum C Programming
    Replies: 16
    Last Post: 11-23-2003, 03:23 PM
  5. ATL: fireing events from a Instanced object
    By CHECCO in forum C++ Programming
    Replies: 2
    Last Post: 09-03-2002, 07:05 AM