Solved

CTreeCtrl Check Box

Posted on 2006-10-27
13
4,384 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
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 

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

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Decoding 32 bit binary streams 6 49
Folder Comparison 12 55
java ^ examples 8 69
Dell Alienware Graphics Amplifier Driver for non-Alienware systems 18 357
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
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.
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

820 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