Solved

CTreeCtrl Check Box

Posted on 2006-10-27
13
4,369 Views
Last Modified: 2013-11-20
Hi...I have a dialog box with a tree control that has check-boxes in it.  What I need to do is, when any of the check-boxes in the tree control is checked, I need to do some processing, and for now let's just say, I need to put up a messagebox.  I added a function for the 'NM_CLICK' message to intercept the left button clicks in the tree control, then I do a 'GetCheck' to see if the button is checked.

When I check the box, the 'GetCheck' function returns a 0 but a checkmark appers in the box.  When I uncheck the box, the 'GetCheck' function returns a 1, and the checkmark is removed from the box.  So this isn't really helping me figure out when the box is checked and not.

Any help would be greatly appericated.

Here is my code for the 'NM_CLICK'

void CDirectoryCheckDlg::OnClickTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
  CPoint pt;
  GetCursorPos(&pt);
  m_testTree.ScreenToClient(&pt);
  UINT uFlags;

   HTREEITEM ht = m_testTree.HitTest(pt, &uFlags);
      
      if(ht != NULL)
      {
            // There is an item under the cursor.
            m_testTree.SelectItem(ht);

            // See what exactly was under the cursor:
            switch(uFlags)
            {
                  case TVHT_ONITEMSTATEICON:
                  {
                        // It is the icon (checkbox)
                        BOOL chkbox = m_testTree.GetCheck(ht);
                              if(chkbox)
                                    MessageBox("Button is checked");
                              
                                     //CString str;
                                    //str.Format("%d",chkbox);
                                   //MessageBox(str,NULL,NULL);
                        break;
                  }
                  case TVHT_ONITEMBUTTON:
                        // It is the button
                        break;

            }


      }



      *pResult = 0;
}
0
Comment
Question by:arunykand
  • 6
  • 5
  • 2
13 Comments
 
LVL 22

Expert Comment

by:mahesh1402
ID: 17824631
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 17824719
Something like following :

              UINT uFlags=0;
      HTREEITEM ht = m_testTree.HitTest(pt, &uFlags);

      if( uFlags & TVHT_ONITEMSTATEICON )
      {
            int iImage = GetItemState( ht, TVIS_STATEIMAGEMASK )>>12;
            SetItemState( ht, INDEXTOSTATEIMAGEMASK(iImage == 1 ? 2 : 1),TVIS_STATEIMAGEMASK );
      }

You may retrieve check state like this :

BOOL IsItemChecked(HTREEITEM hItem)
{
  return GetItemState( hItem, TVIS_STATEIMAGEMASK )>>12 == 2;
}

As per : http://www.codeguru.com/cpp/controls/treeview/misc-advanced/article.php/c663/

-MAHESH
0
 
LVL 5

Expert Comment

by:Nass89
ID: 17824966
Hi,

From MSDN :

>>When the user clicks the check box of a TreeView item, an NM_CLICK notification is sent to the parent window. When >>this occurs, the TVM_HITTEST message returns TVHT_ONITEMSTATEICON. The TreeView control uses this same >>condition to toggle the state of the check box.
>> Unfortunately, the TreeView control toggles the state after the NM_CLICK notification is sent.

>>You can post a user-defined message to the same window that is processing the NM_CLICK notification, and treat this >>user-defined message as a notification that the checked state has changed. Following is sample code that illustrates >>how this can be accomplished:

See Q261289: HOWTO: Know When the User Clicks a Check Box in a TreeView Control

The complete code is written.


Good luck!
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 

Author Comment

by:arunykand
ID: 17825558
I am looking at the MSDN article from above and tried to duplicate the code, but can't get past the compile error for 'MapWindowPoints(HWND_DESKTOP, lpnmh->hwndFrom, &ht.pt, 1)';  error C2661: 'MapWindowPoints' : no overloaded function takes 4 parameters

BOOL CDirectoryCheckDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
      switch(wParam)
               {
            case WM_NOTIFY:
            {
                     LPNMHDR lpnmh = (LPNMHDR) lParam;
                     TVHITTESTINFO ht = {0};
                    
                     if((lpnmh->code  == NM_CLICK) && (lpnmh->idFrom == IDC_TREE1))
                     {
                          DWORD dwpos = GetMessagePos();

                          // include <windowsx.h> and <windows.h> header files
                          ht.pt.x = GET_X_LPARAM(dwpos);
                          ht.pt.y = GET_Y_LPARAM(dwpos);
                          MapWindowPoints(HWND_DESKTOP, lpnmh->hwndFrom, &ht.pt, 1);

                          TreeView_HitTest(lpnmh->hwndFrom, &ht);
         
                          if(TVHT_ONITEMSTATEICON & ht.flags)
                          {
         
                              
                          }
                     }
                    
            break;
            }
            
      }
      
      return CDialog::OnNotify(wParam, lParam, pResult);
}
0
 

Author Comment

by:arunykand
ID: 17825593
Yes I did include include <windowsx.h> and <windows.h> header files
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 17825594
Have u tried with above code given by me with IsItemChecked(HTREEITEM hItem) ?

-MAHESH
0
 

Author Comment

by:arunykand
ID: 17825656
Hi Mahesh,
     I have not tried your method yet....it just seemed like it was more involved that the other one.  It's hard to believe that it seems so simple, yet it's not, just to get the state of a checkbox!!!!

Thanks!
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 17825907
>>It's hard to believe that it seems so simple,

code is from above link of same working solution of checkbox with tree...... download and execute to believe
http://www.codeguru.com/cpp/controls/treeview/misc-advanced/article.php/c663/

-MAHESH
0
 

Author Comment

by:arunykand
ID: 17826045
Mahesh....I seem to be a bit confused with the solution you have mentioned.  Are we supposed to create 3 separate bitmaps, or one bitmap?
0
 

Author Comment

by:arunykand
ID: 17826047
BTW there was no sample code to download and execute in your link.......
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 17826120
ok forget above link........

lets go with yours way : to resolve above error use global API function with scope resolution operator :

::MapWIndowPoints(HWND_DESKTOP, lpnmh->hwndFrom, &ht.pt, 1);


btw To know which Tree Item's check box was clicked in CTreeCtrl.. it will be something like :

// handler of NM_CLICK message
CMyDlg::OnClickTree(......)
{
  DWORD dw = GetMessagePos();
  CPoint pt(GET_X_LPARAM(dw),GET_Y_LPARAM(dw));
  m_Tree.ScreenToClient(&pt);
 
  UINT flags;
  HTREEITEM hItem = m_Tree.HitTest(pt,&flags);
 
  if(hItem)
    TRACE("%s\n",m_Tree.GetItemText(hItem)); // get item text
}

-MAHESH
0
 

Author Comment

by:arunykand
ID: 17826189
Mahesh....first, I apperciate your help.  Second, Either I have no idea what i'm doing, or none of the method's that have been mentioned here are working for me.  

I have the NM_CLICK handler for my tree control, and I can do the HitTest etc, to get my item text and so forth(From my first post).  But to check whether the 'checkbox' has been checked, always seems to be one behind.  That's all I am trying to accomplish.

I did create a WM_NOTIFY message as the other person suggested, to no avail.  It never seems to go into my switch statement....

BOOL CDirectoryCheckDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
      //HWND  hWnd  = AfxGetMainWnd()->m_hWnd;

      NMHDR* pNMHDR = (NMHDR*)lParam;


        //CWnd* hWnd = GetActiveWindow();

      switch(pNMHDR->code)
    {
            case WM_NOTIFY:
            {
                     LPNMHDR lpnmh = (LPNMHDR) lParam;
                     TVHITTESTINFO ht = {0};
   
                    
                     if((lpnmh->code  == NM_CLICK) && (lpnmh->idFrom == IDC_TREE1))
                     {
                          DWORD dwpos = GetMessagePos();

                          // include <windowsx.h> and <windows.h> header files
                          ht.pt.x = GET_X_LPARAM(dwpos);
                          ht.pt.y = GET_Y_LPARAM(dwpos);

                              ::MapWindowPoints(HWND_DESKTOP, lpnmh->hwndFrom, &ht.pt, 1);

                          TreeView_HitTest(lpnmh->hwndFrom, &ht);
         
                          if(TVHT_ONITEMSTATEICON & ht.flags)
                          {
                                MessageBox("hello",NULL,NULL);
         
                                        /::PostMessage(this->m_hWnd, UM_CHECKSTATECHANGE, 0, (LPARAM)ht.hItem);


                          }
                     }
                    
            break;
            }
            case UM_CHECKSTATECHANGE:
                  MessageBox("hi",NULL,NULL);
                  break;
            
      }
      
      return CDialog::OnNotify(wParam, lParam, pResult);
}
0
 
LVL 5

Accepted Solution

by:
Nass89 earned 100 total points
ID: 17827851
Hi,

I checked the codes in MSDN and changed it to the followings:

Add a user defined message to your dialog as here:

//Ofcourse define UM_CHECKSTATECHANGE befor these codes and the function in header file

BEGIN_MESSAGE_MAP(CDirectoryCheckDlg, CDialog)
.....
      ON_MESSAGE(UM_CHECKSTATECHANGE, OnUserMessage)
......
END_MESSAGE_MAP()


Add the following members to your dialog

BOOL CDirectoryCheckDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
      // TODO: Add your specialized code here and/or call the base class
 
      LPNMHDR lpnmh = (LPNMHDR) lParam;
   TVHITTESTINFO ht = {0};
   
   if((lpnmh->code  == NM_CLICK) && (lpnmh->idFrom == IDC_TREE1))
   {
      DWORD dwpos = GetMessagePos();
//      MessageBox("Check", "Click", MB_OK);

      // include <windowsx.h> and <windows.h> header files
      ht.pt.x = GET_X_LPARAM(dwpos);
      ht.pt.y = GET_Y_LPARAM(dwpos);
      ::MapWindowPoints(HWND_DESKTOP, lpnmh->hwndFrom, &ht.pt, 1);

      TreeView_HitTest(lpnmh->hwndFrom, &ht);
         
      if(TVHT_ONITEMSTATEICON & ht.flags)
      {
         
         PostMessage(UM_CHECKSTATECHANGE, 500, (LPARAM)ht.hItem);
      }
   }
      
      return CDialog::OnNotify(wParam, lParam, pResult);
}
void
CDirectoryCheckDlg::OnUserMessage(WPARAM wParam, LPARAM lParam)
{
      

  HTREEITEM   hItemChanged = (HTREEITEM)lParam;

  if(m_testTree.GetCheck(hItemChanged))
      MessageBox("It is really checked", "Hiiiiiiiiiii", MB_OK);
  else
      MessageBox("IT IS NOT CHECKECD", "Hiiiiiiiiiii", MB_OK);


}

I tested the above codes and it works!!!!

Try it and good luck!


0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Installing Microsoft R server on REDHAT or SUSE Linux 4 138
Hibernate methods 2 72
modThree challenge 4 91
fix34  challenge 9 123
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …

803 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question