Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3870
  • Last Modified:

How to change a selected item in CListCtrl to not_selected without the click action

Hello, Experts:
 I need your help !
 you may think my question is very strange, but I have to solve this because my client stick to this feature.
 my situation is, I have a CListCtrl in my dialog,and list items with checkbox. the feature of the CListCtrl need to satisfy following:
1) when click and select an item, only this item must be checked and selected.
2) when check on the checkbox of an item, this item must be checked and selected, other selected item must be turn to unselected state.
3) when uncheck on the checkbox of an item, this item must be unchecked and unselected.

I finished 1), but I have problem to do 2) &3),  I tried use OnItemChangedListCtrl to check the status and then try to make the item selected/unselected. but I failed.
Can somebody kindly tell me the possible solution? please tell me if I had use the event-handle and also how to make a selected item to unselected state.
Thank you very much !

-- pigangel with big headache
0
pigangel
Asked:
pigangel
  • 6
  • 3
1 Solution
 
migelCommented:
Hi!
You have to derive your clas fom CListCtrl and handle WM_LBUTTONDOWN message or reflected NM_CLICK message (IMHO 1 way is preffered)
In this hadler you must determine where click occured (using CListCtrl::HitTest member) and implement checking unchecking.
Since only one item must be checked you can store in the class checked itemId and use in the future.
in the pseudocode alg to keep only one item checked:
WM_LBUTTONDOWN
{
nClickedItem  = .... ;
if (HitTest() == LVHT_ONITEMSTATEICON)
  {
 
  if (m_CheckedId == -1)
     {
     CheckItem(nClickedItem = m_CheckedId);
     }
  else
     {
     UncheckItem(CheckedId);
     if (m_CheckedId != nClickedItem)
       {
     CheckItem(nClickedItem = m_CheckedId);
       }
    else
       m_CheckedId = -1;
     }
  }
}
0
 
DanRollinsCommented:
Can you use the MFC class CCheckListbox?  

It provides both a "Selection changed" and a "check changed" notifications.  It should be easy to implement your requirement if you know whenever either of these events occur.

-- Dan
0
 
DanRollinsCommented:
To change the selected item in a CListCtrl, you need to use:

SetItme.  FOr instance,

BOOL fRet= m_ctlList.SetItem( 1, 0, LVIF_STATE, 0, 0, LVIS_SELECTED, LVIS_SELECTED, 0 );

This handler displays all the info you need to know.  Be aware that before an item gets selected, another item gets unselected.  

void CMyDlg::OnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult)
{
     NMLISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    if ( pNMListView->uChanged & LVIF_STATE ) {
        // MessageBox("State change");
        int nItem= pNMListView->iItem;
        int nNewState= pNMListView->uNewState;
        int nOldState= pNMListView->uOldState;
        CString sSel= "NOT Selected";
        if ( nNewState & LVIS_SELECTED ) {
            sSel= "Selected";
        }
        CString sChecked= "NOT Checked";
        if ( m_ctlList.GetCheck(nItem) ) {
            sChecked= "Checked";
        }
        CString sMsg;
        sMsg.Format("item %d is %s/%s  (State=%04x)", nItem, (LPCSTR)sChecked, (LPCSTR)sSel, nNewState );

        MessageBox(sMsg);
    }    
     *pResult = 0;
}


THis handler will be called even when you change the selection or check programatically (it does not depend on the user clicking anything)

-- Dan
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
pigangelAuthor Commented:
Hi,migel & Dan:
  thanks to both of you! from Dan's example, I got to know deeply about the actions of click and check(box). and I tried migel's proposal to use OnClickListCtrl() and implemented like following :

Mydlg::OnCliclListCtrl(...)
{

     int           nSel;

     NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

     nSel = pNMListView->iItem;
     
     if(nSel != -1) {
         
          for(int i=0;i < m_lstMachineType.GetItemCount(); i++ ) {
               if (i != nSel ) {
                    m_lstMachineType.SetCheck(i,FALSE);
                    // **** set the item to unselected state.
                    //m_lstMachineType.SetItem( i, 0, LVIF_STATE, 0, 0, 0, 0, 0 );
                    //m_lstMachineType.SetItemState(i,LVIS_SELECTED,0);

               }
          }

          m_lstMachineType.SetCheck(nSel,TRUE);
          m_lstMachineType.SetItemState(nSel,LVIS_SELECTED,LVIS_SELECTED);
     }else{

          for(int i=0;i < m_lstMachineType.GetItemCount(); i++ ) {
                    m_lstMachineType.SetCheck(i,FALSE);
          }
     }


     *pResult = 0;


}


I almost get the features done, but that I tried SetItemState method,  but I could set the item to unselected state (please see my comment *** in the code part), can you please kindly how to do it ? thank you very much!


-- pigangel
0
 
DanRollinsCommented:
If your testing code implements my hander as well as you OnClick, then you are experiencing a conflict because of that.
-=-==-=--=-==--=-==-=-=-
As I said:
To change the selected item in a CListCtrl, you need to use SetItem.  For instance,

BOOL fRet= m_ctlList.SetItem( 1, 0, LVIF_STATE, 0, 0, LVIS_SELECTED, LVIS_SELECTED, 0 );

So, to unselect an item, use:

BOOL fRet= m_ctlList.SetItem( 1, 0, LVIF_STATE, 0, 0, 0, LVIS_SELECTED, 0 );

That is, set statemask to LVIS_SELECTED and state to 0.

Note that because you are doing this in an OnClick handler, the actions you perform may be undone by the system as soon as you are finished.  I've seen some strange results because of the way MS implemented the 'check' feature of this control.  If you watch the default action closely, the control first changes the selection, then sets the check, then puts the old selection back.

If you insist on handling this in your OnClick handler, I recommend posting a message to yourself, say UM_MySetAllItemStates.  In your handler for that, you could go through the entire list checking/unchecking selecting/unselectiong as needed.

-- Dan
0
 
pigangelAuthor Commented:
I used SetItem to change the selected item, it was  successful to change the item state. I am very happy though
there are still strange results like Dan mentioned, at least I am very close to the features.
thank you very much! I will try your proposal to see how I can solve the strange result.

-- pigangel
0
 
DanRollinsCommented:
Hi pigangel,

Do you have any additional questions?  Do any comments need clarification?

-- Dan
0
 
DanRollinsCommented:
hi pigangel,

Do you have any additional questions?  Do any comments need clarification?

-- Dan
0
 
DanRollinsCommented:
hi pigangel,

Do you have any additional questions?  Do any comments need clarification?

-- Dan
0
 
pigangelAuthor Commented:
Hi,Dan:
  sorry to be late to accept your answer, I have been busy with field test. thank you very mcuh! your answer is the exact one for my question!
 
  Thanks to migel too, I will try the suggestion to see how it satisfy the whole 3 features.

-- pigangel
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 6
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now