Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Limiting selected checkbox items in a CListCtrl

Limiting selected checkbox items in a CListCtrl

Scheduled Pinned Locked Moved C / C++ / MFC
questionlearning
4 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    softwaremonkey
    wrote on last edited by
    #1

    I have a CListCtrl with the LVS_EX_CHECKBOXES style and I want to limit the number of items that the user can select. I have written the following code but (of course) it gets itself in a loop because in changing the state of an item, it causes OnItemchangingLoadingValues() to be called again.

    void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
    {
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    int nCheckedItems = 0;
    for(int i = 0; i < m_loadingVals.GetItemCount(); i++)
    {
    BOOL bState = ListView_GetCheckState(m_loadingVals.m_hWnd, i);
    if(bState)
    {
    nCheckedItems++;
    }
    }

    if(nCheckedItems == 2)
    {
    	ListView\_SetItemState(m\_loadingVals.m\_hWnd, pNMListView->iItem, FALSE, LVIS\_STATEIMAGEMASK);
    }
    
    \*pResult = 0;
    

    }

    What is the correct way to go about doing this? :~

    D J 2 Replies Last reply
    0
    • S softwaremonkey

      I have a CListCtrl with the LVS_EX_CHECKBOXES style and I want to limit the number of items that the user can select. I have written the following code but (of course) it gets itself in a loop because in changing the state of an item, it causes OnItemchangingLoadingValues() to be called again.

      void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
      {
      NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
      int nCheckedItems = 0;
      for(int i = 0; i < m_loadingVals.GetItemCount(); i++)
      {
      BOOL bState = ListView_GetCheckState(m_loadingVals.m_hWnd, i);
      if(bState)
      {
      nCheckedItems++;
      }
      }

      if(nCheckedItems == 2)
      {
      	ListView\_SetItemState(m\_loadingVals.m\_hWnd, pNMListView->iItem, FALSE, LVIS\_STATEIMAGEMASK);
      }
      
      \*pResult = 0;
      

      }

      What is the correct way to go about doing this? :~

      D Offline
      D Offline
      David Crow
      wrote on last edited by
      #2

      softwaremonkey wrote:

      because in changing the state of an item, it causes OnItemchangingLoadingValues() to be called again.

      But the parameters (i.e., state) passed each time are different. Rather than use a for() loop each time an item's state changes, simply check the state passed and use a counter. Then in OnItemchangingLoadingValues(), you could have something like:

      void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
      {
      if (nCheckedItems < 2)
      {
      if (pNMHDR's new state equals checked)
      nCheckedItems++;
      else
      nCheckedItems--;
      }
      }

      "One man's wage rise is another man's price increase." - Harold Wilson

      "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

      "Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous

      1 Reply Last reply
      0
      • S softwaremonkey

        I have a CListCtrl with the LVS_EX_CHECKBOXES style and I want to limit the number of items that the user can select. I have written the following code but (of course) it gets itself in a loop because in changing the state of an item, it causes OnItemchangingLoadingValues() to be called again.

        void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
        {
        NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
        int nCheckedItems = 0;
        for(int i = 0; i < m_loadingVals.GetItemCount(); i++)
        {
        BOOL bState = ListView_GetCheckState(m_loadingVals.m_hWnd, i);
        if(bState)
        {
        nCheckedItems++;
        }
        }

        if(nCheckedItems == 2)
        {
        	ListView\_SetItemState(m\_loadingVals.m\_hWnd, pNMListView->iItem, FALSE, LVIS\_STATEIMAGEMASK);
        }
        
        \*pResult = 0;
        

        }

        What is the correct way to go about doing this? :~

        J Offline
        J Offline
        Jochen Arndt
        wrote on last edited by
        #3

        You may add a member variable to your class (or a static variable to the handler function) indicating that the handler is called recursive:

        // Header file
        private:
        m_bIgnoreChgHandling;

        // Source file
        CSpecimenLoadingDialog::CSpecimenLoadingDialog()
        {
        m_bIgnoreChgHandling = false;
        }

        void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
        {
        // Alternative: Use static variable here
        // static bool m_bIgnoreChgHandling = false;
        if (!m_bIgnoreChgHandling)
        {
        NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
        int nCheckedItems = 0;
        // some handling code
        if(nCheckedItems == 2)
        {
        m_bIgnoreChgHandling = true;
        ListView_SetItemState(m_loadingVals.m_hWnd, pNMListView->iItem, FALSE, LVIS_STATEIMAGEMASK);
        m_bIgnoreChgHandling = false;
        }
        }
        *pResult = 0;
        }

        S 1 Reply Last reply
        0
        • J Jochen Arndt

          You may add a member variable to your class (or a static variable to the handler function) indicating that the handler is called recursive:

          // Header file
          private:
          m_bIgnoreChgHandling;

          // Source file
          CSpecimenLoadingDialog::CSpecimenLoadingDialog()
          {
          m_bIgnoreChgHandling = false;
          }

          void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
          {
          // Alternative: Use static variable here
          // static bool m_bIgnoreChgHandling = false;
          if (!m_bIgnoreChgHandling)
          {
          NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
          int nCheckedItems = 0;
          // some handling code
          if(nCheckedItems == 2)
          {
          m_bIgnoreChgHandling = true;
          ListView_SetItemState(m_loadingVals.m_hWnd, pNMListView->iItem, FALSE, LVIS_STATEIMAGEMASK);
          m_bIgnoreChgHandling = false;
          }
          }
          *pResult = 0;
          }

          S Offline
          S Offline
          softwaremonkey
          wrote on last edited by
          #4

          Clever stuff - thanks :thumbsup:

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups