Link to home
Create AccountLog in
Avatar of thready
thready

asked on

CListCtrl Visual C++ 6.0 - programmatically change selected rows OnItemChanged

Hi Experts,
I'm using an MFC CListCtrl in Visual C++ 6.0 and when a selection changed, I am selecting the chunks of 3 lines around it. - i.e., if I am selecting line number 4, I also want to select line 3 and line 5.

I momentarily see the lines getting selected but they are being deselected immediately after....
Avatar of jkr
jkr
Flag of Germany image

Are you sure that LVS_SINGLESEL is *not* set?
Avatar of thready
thready

ASKER

positive.. actually, my code works when I press the down arrow...  When I click, if I keep the left mouse button down, the selection stays... When I release, the selection disappears...

Here's the code:
void CMyView::OnItemchangedData(NMHDR* pNMHDR, LRESULT* pResult)
{
      NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

      if ( !(pNMListView->uNewState & LVIS_SELECTED) )
            return;

      int nIndex = CStringHelper::ListCtrlGetSelItemIndex(m_Data);
      if(nIndex != -1)
            SelectedIndex(nIndex);

      *pResult = 0;
}

// depending on nIndex, 3 lines will get selected...
void CMyView::SelectedIndex(int nIndex)
{
      // first deselect everything:
//      CStringHelper::ListCtrlDeselectAll(m_Data);
      
      int nFirstIndex = nIndex / 3;
      nFirstIndex *= 3;   // this does have an effect - since nFirstIndex is an INT, it takes the result without remainder....

      for(int i = 0; i < 3; i++)
            CStringHelper::ListCtrlHighlightAndEnsureVisible(m_Data, nFirstIndex + i);
}

      static int ListCtrlGetSelItemIndex(CListCtrl & List)
      {
            int  nIndex = -1;
            if(List && ::IsWindow(List.m_hWnd) && List.GetSelectedCount() > 0 )
            {
                  POSITION pos= List.GetFirstSelectedItemPosition();
                  if (pos != NULL)
                        nIndex = List.GetNextSelectedItem(pos);
            }
            return nIndex;
      }

      static void ListCtrlDeselectAll(CListCtrl & List)
      {
            for(int i = 0; i < List.GetItemCount(); i++)
                  List.SetItemState(i, 0, 0);
      }

      static void ListCtrlHighlightAndEnsureVisible(CListCtrl & List, int nIndex)
      {
            List.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED);
            List.EnsureVisible(nIndex, FALSE);
      }
OK, just wanted to be sure ;o)

What happens if you use

      static void ListCtrlHighlightAndEnsureVisible(CListCtrl & List, int nIndex)
      {
            List.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED);
            List.EnsureVisible(nIndex, FALSE);
      }

instead?
Avatar of thready

ASKER

Thanks for your response - same thing happens - I get 3 lines highlighted and then as soon as I release the mouse button, the actual line I clicked on is highlighted...  There has to be a quick fix for this... I have a feeling it's a function like "OnMouseUp" getting called which selects the last clicked item... If I override that function and do nothing, my selection should stay... I'm thinking this because of it working when I use the down arrow....  It even worked ONCE out of about 100 clicks (the 3 line selection stayed)!!  Timing of some asynchronous function call.....

Mike

Avatar of thready

ASKER

ok I realized what made it work when I clicked on it that one time.... I can do it every time now... Basically, whichever row I click on, say row 5, if I drag away from row 5 without releasing and let go on row 4, I get my 3 line selection.  For some reason, letting go on the same index causes the selection to change to only the clicked row..... The answer is near.......  Hmmmmmmm..............
Hm, sorry, drawing a blank at the moment...
Avatar of thready

ASKER

Another hint:  if I right-click, it works (even on release of the button).  Left-click causes the 3 lines to get selected and releasing selects the item I'm over unless I've dragged off the one that the left mouse down was originally on...  i.e., if I left click on 4, I get lines 3, 4 and 5 highlighted, and if I release on 4, only 4 is highlighted.  But if I release on 5 instead, 3, 4 and 5 stay highlighted.  Right clicking on 4 works perfectly in either case.....

What does left clicking call that right clicking does not?  That is how I should rephrase this question.  For one, it calls new selection code.  Which code??  =)  Little bugger.
Why not select the rows based on a mouse event (mouse down and/or up) in the view.
>>>>  int nFirstIndex = nIndex / 3;
>>>>  nFirstIndex *= 3;  
That turns any index to the next lower multiple of 3, e. g. line 4 and line 5 got the same nFirstIndex. That is hardly what you intend to do?

Regards, Alex
Avatar of thready

ASKER

Hey Alex, yes, that's what I'm looking for.... The app I'm writing requires it for display purposes (each line is really like 3 lines)...

Andy - I think that's a good idea - I was getting a problem with setting a selection in OnItemchangedData since it was causing infinite recursion and I couldn't figure out how to stop it.... I'll try it!  Let you know at the end of the day... Very little internet access later....  Thanks!
<I was getting a problem with setting a selection in OnItemchangedData since it was causing infinite recursion>

I had that as a worry about the way you were attempting it..  Let the view do the default behaviour for the mouse event then run you code to select the three lines.
Avatar of thready

ASKER

Do I need to GetView off my CListCtrl?  I'm not sure how to do this.... Is there a way to set a new view for my CListCtrl that handles the mouse clicks?  Hmm....
Your earlier comments had the class CMyView - handle the mouse click there.
Avatar of thready

ASKER

That's the view in an MDI app - How do I know what index was clicked on... Do I have to do gymnastics in figuring out the client click position and where the scrollbar in my list is set?
Is it a CListView based view?

If you let the base class handle the mouse event then that will perform the default behaviour and select the line you clicked on.  Then just interrogate the list control to find out what line is selected and perform your routine to select the three lines.
SOLUTION
Avatar of itsmeandnobodyelse
itsmeandnobodyelse
Flag of Germany image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Avatar of thready

ASKER

Thanks Alex for your infinite recursion blocker!

Andy - my list is a CLIstCtrl - not a CListView... Actually, it's a class that extends CListCtrl (CEditableListCtrl - my own)....

ASKER CERTIFIED SOLUTION
Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.