Solved

CTreeCtrl Check Box

Posted on 2006-10-27
13
4,206 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
 

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
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

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

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
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 video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

708 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now