CListCtrl : Fastest Method To Get Selected Items ?
Raja Segar -- rsz@pc.jaring.my Friday, January 03, 1997 Environment: Win95, NT 3.51, Visual C++ 4.2b Patched Hi there, Here is the situation. Finding the current selected item in the CListCtrl or all the selected items is unbearingly slow if the number of items in a ListCtrl in report mode is > 3000 ++. BTW i hardcoded the CListCtrl to be in Report Mode only. I have a Pentium 133 with 32Mb Ram. That's a pretty fast machine. At first i taught it would be as easy as listbox but was i wrong. All the info i could find was to use the method below. ... ... int y = 0; int start = -1 ; while ( (y = this->GetNextItem (start++, LVNI_SELECTED )) >=0 ) { pItem->iItem = y; ... ... } Too damn slow for my liking especially if the selected item are at the very bottom. So i figured it would be much faster to keep a list of all the selected items as they are clicked or selected. Good Idea . But then i find out the hard way the OnClick method does not return the current item. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; CurItem = pNMListView.iItem; The only bad news is that CurItem is always 655320 :( Then i taught i could use the item changing messages. LVN_ITEMCHANGED & LVN_ITEMCHANGING. Man they worked .. i taught all my problems were over but for some weird reason each of the method is getting fired 3 or 4 times for a simple click? Err .. handling this situation would be tricky. Plus i would have to handle all the clicks with the ctrl key or shift key held down ...wooooohhh this would be very complicated. So i taught i should consult the experts before doing this. So here i am ... Anyone with any info on this matter please help out. Thanks in advance. Bye .. Happy Holidays. ( _ \/ __)(_ ) ) /\__ \ / /_ (_)\_)(___/(____)@pc.jaring.my
Dean Wiles -- deanw@isc-br.isc-br.com Friday, January 03, 1997 > From: Raja Segar> To: mfc-l@netcom.com > Subject: CListCtrl : Fastest Method To Get Selected Items ? > Date: Friday, January 03, 1997 5:35 AM > > Environment: Win95, NT 3.51, Visual C++ 4.2b Patched > > > Hi there, > > Here is the situation. > Finding the current selected item in the CListCtrl or all the > selected items is unbearingly slow if the number of items in > a ListCtrl in report mode is > 3000 ++. > BTW i hardcoded the CListCtrl to be in Report Mode only. > > I have a Pentium 133 with 32Mb Ram. That's a pretty fast machine. > > At first i taught it would be as easy as listbox but was i wrong. > All the info i could find was to use the method below. > > ... > ... > int y = 0; > int start = -1 ; > while ( (y = this->GetNextItem (start++, LVNI_SELECTED )) >=0 ) > { > pItem->iItem = y; > ... > ... > } > > Too damn slow for my liking especially if the selected item are > at the very bottom. > > So i figured it would be much faster to keep a list of all the selected > items as they are clicked or selected. Good Idea . > > But then i find out the hard way the OnClick method does not return the > current item. > NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; > CurItem = pNMListView.iItem; > The only bad news is that CurItem is always 655320 :( > > Then i taught i could use the item changing messages. > LVN_ITEMCHANGED & LVN_ITEMCHANGING. > > Man they worked .. i taught all my problems were over but > for some weird reason each of the method is getting fired 3 or 4 > times for a simple click? > > Err .. handling this situation would be tricky. Plus i would have > to handle all the clicks with the ctrl key or shift key held down > ...wooooohhh this would be very complicated. > > So i taught i should consult the experts before doing this. > So here i am ... > > Anyone with any info on this matter please help out. > Thanks in advance. > Bye .. Happy Holidays. > > > > > > > > ( _ \/ __)(_ ) > ) /\__ \ / /_ > (_)\_)(___/(____)@pc.jaring.my > I ran into a similar situation, and went a similar course. I kept my own list of elements in a CStringArray and then save the current selection in LVN_ITEMCHANGED and use that for NM_CLICK and NM_RETURN: class CMyView : public CFormView { ... CStringArray m_astrItem; int m_iSelectedItem; LPARAM m_lSelectedID; ... }; ... BEGIN_MESSAGE_MAP(CMyView, CFormView) //{{AFX_MSG_MAP(CMyView) ON_NOTIFY(LVN_GETDISPINFO, IDC_MY_LIST, OnGetdispinfoMyList) ON_NOTIFY(LVN_ITEMCHANGED, IDC_MY_LIST, OnItemChangedMyList) ON_NOTIFY(NM_CLICK, IDC_MY_LIST, OnClickMyList) ON_NOTIFY(NM_RETURN, IDC_MY_LIST, OnReturnMyList) //}}AFX_MSG_MAP ... END_MESSAGE_MAP() ... void CMyView::OnGetdispinfoMyList(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; LV_ITEM* pItem = &pDispInfo->item; // See if we need to provide text for item if (pItem->mask & LVIF_TEXT) { ASSERT(pItem->pszText != NULL && pItem->cchTextMax > 0); // Display text for item/subitem from array // My CStringArray is used internally as a 2-D array that is TABLE_WIDTH wide _tcsncpy(pItem->pszText, m_astrItem[pItem->iItem * TABLE_WIDTH + pItem->iSubItem], pItem->cchTextMax); pItem->pszText[pItem->cchTextMax - 1] = '\0'; // In case str truncated } *pResult = 0; } void CMyView::OnItemChangedMyList(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; if ((pNMListView->uChanged & LVIF_STATE) && (pNMListView->uNewState & LVIS_SELECTED) && !(pNMListView->uOldState & LVIS_SELECTED)) // If item was just selected { m_iSelectedItem = pNMListView->iItem; // Save selected item and ID m_lSelectedID = pNMListView->lParam; } *pResult = 0; } void CMyView::OnClickMyList(NMHDR* pNMHDR, LRESULT* pResult) { if (m_iSelectedItem != -1) // User clicked item { DoSomething(m_iSelectedItem, m_lSelectedID); // Display selected item } *pResult = 0; } void CMyView::OnReturnMyList(NMHDR* pNMHDR, LRESULT* pResult) { if (m_iSelectedItem != -1) // User pressed enter on item { DoSomething(m_iSelectedItem, m_lSelectedID); // Display selected item } *pResult = 0; } void CMyView::DoSomething(int iItem, LPARAM lID) { // Display selected item ... } Hope this helps. Dean. -------------------------------------------------------------------------- Dean Wiles (deanw@mail.isc-br.com) Olivetti North America Phone: (509)927-7037 22425 East Appleway Ave Fax: (509)927-2499 Liberty Lake, WA 99019-9534 If the Son sets you free, you will be free indeed. (John 8:36)
Kenneth A. Argo -- argo@rias.COM Friday, January 03, 1997 [Mini-digest: 2 responses] I did it exactly the way you found. You should make a note that there is a flag (uNewState) that you should = query to see what is happening to the item. Below is a snipit from my code which has appeared to function properly = without any problems. My case differs from you in that I do not need to keep a list, I just = need to keep the selected item around so I don't have to find the = selected item later. if (pNMListView->uNewState & LVIS_SELECTED) { TRACE0("New item selected\n"); m_iCurrentSel =3D pNMListView->iItem; // If "Open" wasn't enabled before, enable it now GetParent()->GetDlgItem(IDOK)->EnableWindow(); CString *pcsCaseID =3D (CString = *)m_cListBox.GetItemData(m_iCurrentSel); m_cCaseNumber.SetWindowText(*pcsCaseID); } else if (m_iCurrentSel !=3D -1 && pNMListView->uOldState & = LVIS_SELECTED) { } ---------- From: Raja Segar[SMTP:rsz@pc.jaring.my] Sent: Friday, January 03, 1997 8:36 AM To: mfc-l@netcom.com Subject: CListCtrl : Fastest Method To Get Selected Items ? Environment: Win95, NT 3.51, Visual C++ 4.2b Patched=20 Hi there, =20 Here is the situation. Finding the current selected item in the CListCtrl or all the selected items is unbearingly slow if the number of items in a ListCtrl in report mode is > 3000 ++. BTW i hardcoded the CListCtrl to be in Report Mode only. =20 I have a Pentium 133 with 32Mb Ram. That's a pretty fast machine. At first i taught it would be as easy as listbox but was i wrong. All the info i could find was to use the method below. ... ... int y =3D 0; int start =3D -1 ;=20 while ( (y =3D this->GetNextItem (start++, LVNI_SELECTED )) >=3D0 ) { pItem->iItem =3D y; ... ... } Too damn slow for my liking especially if the selected item are at the very bottom. So i figured it would be much faster to keep a list of all the = selected items as they are clicked or selected. Good Idea . =20 But then i find out the hard way the OnClick method does not return = the current item.=20 NM_LISTVIEW* pNMListView =3D (NM_LISTVIEW*)pNMHDR; CurItem =3D pNMListView.iItem; The only bad news is that CurItem is always 655320 :( Then i taught i could use the item changing messages. LVN_ITEMCHANGED & LVN_ITEMCHANGING. Man they worked .. i taught all my problems were over but for some weird reason each of the method is getting fired 3 or 4 times for a simple click?=20 Err .. handling this situation would be tricky. Plus i would have to handle all the clicks with the ctrl key or shift key held down=20 ...wooooohhh this would be very complicated.=20 So i taught i should consult the experts before doing this.=20 So here i am ... =20 Anyone with any info on this matter please help out. Thanks in advance. Bye .. Happy Holidays. =20 =20 =20 ( _ \/ __)(_ ) ) /\__ \ / /_=20 (_)\_)(___/(____)@pc.jaring.my -----From: "Mittal, Vineet"In the OnClick event use HitTest to get the index. Here is the code void CMyList::OnClickList(NMHDR* pNMHDR, LRESULT* pResult) { CPoint curPoint; GetCursorPos(&curPoint); ScreenToClient(&curPoint); LV_HITTESTINFO tmp; tmp.pt = curPoint; tmp.flags = LVHT_ONITEM; m_List.HitTest(&tmp); *pResult = 0; } tmp.iItem would give the index of the currently clicked item. Hope it helps Vineet ---------- From: owner-mfc-l To: mfc-l Subject: CListCtrl : Fastest Method To Get Selected Items ? Date: Friday, January 03, 1997 9:35PM Environment: Win95, NT 3.51, Visual C++ 4.2b Patched Hi there, Here is the situation. Finding the current selected item in the CListCtrl or all the selected items is unbearingly slow if the number of items in a ListCtrl in report mode is > 3000 ++. BTW i hardcoded the CListCtrl to be in Report Mode only. I have a Pentium 133 with 32Mb Ram. That's a pretty fast machine. At first i taught it would be as easy as listbox but was i wrong. All the info i could find was to use the method below. ... ... int y = 0; int start = -1 ; while ( (y = this->GetNextItem (start++, LVNI_SELECTED )) >=0 ) { pItem->iItem = y; ... ... } Too damn slow for my liking especially if the selected item are at the very bottom. So i figured it would be much faster to keep a list of all the selected items as they are clicked or selected. Good Idea . But then i find out the hard way the OnClick method does not return the current item. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; CurItem = pNMListView.iItem; The only bad news is that CurItem is always 655320 :( Then i taught i could use the item changing messages. LVN_ITEMCHANGED & LVN_ITEMCHANGING. Man they worked .. i taught all my problems were over but for some weird reason each of the method is getting fired 3 or 4 times for a simple click? Err .. handling this situation would be tricky. Plus i would have to handle all the clicks with the ctrl key or shift key held down ...wooooohhh this would be very complicated. So i taught i should consult the experts before doing this. So here i am ... Anyone with any info on this matter please help out. Thanks in advance. Bye .. Happy Holidays. ( _ \/ __)(_ ) ) /\__ \ / /_ (_)\_)(___/(____)@pc.jaring.my
Greg Lose -- glose@ArkansasUSA.com Friday, January 03, 1997 Raja - My list is cathcing the OnChange message and seems to be working great. Below is the code I'm using NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; CString theBuffer; if((pNMListView->uNewState & LVIS_SELECTED) != 0 ) { LV_ITEM ListItem; ListItem.mask = LVIF_TEXT; ListItem.iItem = pNMListView->iItem; ListItem.iSubItem = 0; ListItem.pszText = theBuffer.GetBuffer(50); ListItem.cchTextMax = 50; m_MyList->GetItem(&ListItem); theBuffer.ReleaseBuffer(); m_CurrSelected = theBuffer; m_SelectedItem = pNMListView->iItem; FireSelectionChanged(); } *pResult = 0; Hope this helps Greg Lose DOCS, Inc. ---------- > From: Raja Segar> To: mfc-l@netcom.com > Subject: CListCtrl : Fastest Method To Get Selected Items ? > Date: Friday, January 03, 1997 7:35 AM > > Environment: Win95, NT 3.51, Visual C++ 4.2b Patched > > > Hi there, > > Here is the situation. > Finding the current selected item in the CListCtrl or all the > selected items is unbearingly slow if the number of items in > a ListCtrl in report mode is > 3000 ++. > BTW i hardcoded the CListCtrl to be in Report Mode only. > > I have a Pentium 133 with 32Mb Ram. That's a pretty fast machine. > > At first i taught it would be as easy as listbox but was i wrong. > All the info i could find was to use the method below. > > ... > ... > int y = 0; > int start = -1 ; > while ( (y = this->GetNextItem (start++, LVNI_SELECTED )) >=0 ) > { > pItem->iItem = y; > ... > ... > } > > Too damn slow for my liking especially if the selected item are > at the very bottom. > > So i figured it would be much faster to keep a list of all the selected > items as they are clicked or selected. Good Idea . > > But then i find out the hard way the OnClick method does not return the > current item. > NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; > CurItem = pNMListView.iItem; > The only bad news is that CurItem is always 655320 :( > > Then i taught i could use the item changing messages. > LVN_ITEMCHANGED & LVN_ITEMCHANGING. > > Man they worked .. i taught all my problems were over but > for some weird reason each of the method is getting fired 3 or 4 > times for a simple click? > > Err .. handling this situation would be tricky. Plus i would have > to handle all the clicks with the ctrl key or shift key held down > ...wooooohhh this would be very complicated. > > So i taught i should consult the experts before doing this. > So here i am ... > > Anyone with any info on this matter please help out. > Thanks in advance. > Bye .. Happy Holidays. > > > > > > > > ( _ \/ __)(_ ) > ) /\__ \ / /_ > (_)\_)(___/(____)@pc.jaring.my
Mike Blaszczak -- mikeblas@nwlink.com Saturday, January 04, 1997 At 21:35 1/3/97 +0800, Raja Segar wrote: >Environment: Win95, NT 3.51, Visual C++ 4.2b Patched > All the info i could find was to use the method below. > int y = 0; > int start = -1 ; > while ( (y = this->GetNextItem (start++, LVNI_SELECTED )) >=0 ) > { > pItem->iItem = y; > ... > ... > } This is very wrong: you're doing far more work than you need to. Unless your loop changes the selected item, you should continue searching by using the last item you found, not by using an incremented count. Like this: int y = -1; while ( (y = this->GetNextItem (y, LVNI_SELECTED )) >=0 ) { pItem->iItem = y; // do work with it ... } It's hard to fathom how your code would work, anyway--it seems like your loop would repeatedly process selected items since the way you're searching for them ends up finding the same item again and again. If you're doing something expensive with each iteration of the loop, that would certainly account for your code's poor performance! If you have three thousand items and the 2700th item is selected, not only will you call GetNextItem() 3000 times, you'll process the 2700th item 2700 times! My modified loop would only call GetNextItem() twice, and only process the 2700th item a single time. It seems like you could have noticed this problem in your code by tracing through it yourself just once. .B ekiM http://www.nwlink.com/~mikeblas/ I'm afraid I've become some sort of speed freak. These words are my own. I do not speak on behalf of Microsoft.
Mario Contestabile -- Mario_Contestabile.UOS__MTL@UOSMTL2.universal.com Monday, January 06, 1997 const INT nSelected = m_ListCtrl.GetSelectedCount(); if( nSelected > 1){ // multiple selection CMapIntToString mapSelection; INT state = -1; // start from top for(INT done = 0; done < nSelected; done++){ if( (state = m_ListCtrl.GetNextItem(state, LVNI_SELECTED)) != -1){ mapSelection[done] = m_ListCtrl.GetItemText(state, 0); TRACE1("%s is selected\n", m_ListCtrl.GetItemText(state, 0) ); }else{ break; } } } mcontest@universal.com ====== Snip ========= int y =3D 0; int start =3D -1 ;=20 while ( (y =3D this->GetNextItem (start++, LVNI_SELECTED )) >=3D0 ) { pItem->iItem =3D y; ... ... } Too damn slow for my liking especially if the selected item are at the very bottom.
| Вернуться в корень Архива |