Solved

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

Posted on 2001-08-15
10
3,849 Views
Last Modified: 2013-11-20
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
Comment
Question by:pigangel
  • 6
  • 3
10 Comments
 
LVL 12

Expert Comment

by:migel
ID: 6389470
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6391393
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6391502
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
 

Author Comment

by:pigangel
ID: 6396476
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6398203
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
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

 

Author Comment

by:pigangel
ID: 6403072
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6420473
Hi pigangel,

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

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6420477
hi pigangel,

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

-- Dan
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 150 total points
ID: 6443892
hi pigangel,

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

-- Dan
0
 

Author Comment

by:pigangel
ID: 6444024
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

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
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 demonstrates a quick way of adding group price to multiple Magento products.

760 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

19 Experts available now in Live!

Get 1:1 Help Now