I`m using Delphi 5, from way back when, and am having huge difficulties
with a TListView.
My list of items is over 16000 and I require a procedure which with
every item selected, adds a property from that selected items associated
object into a stringlist. However two things seem not to work when using
an OwnerData/OnData list.
1; When selecting a number of items using a click for the first item,
and then holding shift and clicking on the last desired item, the
onselectitem event is not called at all after the first click, therefore
missing out a whole list of selected items and deselected items.
2; When the event is called for an item that has just lost its selection
(due to another item being selected etc) the OnSelectItem event is
called with Selcted = False but the Item object is nil.
Basically, I`m hoping somebody here is able suggest how I can get around
this problem.
Currently, instead of just adding/removing the data for the respective
selected/deselected items as the selection event is called, I`m having
to go through the entire list using getnextitem and reconstructing the
stringlist of data each time. This seems like quite an overhead with
16000+ items (this grows monthly by 200 or so entries)
thank you for any help
> 1; When selecting a number of items using a click for the first item, and
> then holding shift and clicking on the last desired item, the onselectitem
> event is not called at all after the first click, therefore missing out a
> whole list of selected items and deselected items.
It is not supposed to. The OnSelectItem event is fired in reply to the
LVN_ITEMCHANGED message, which is not sent for item ranges in an owner-data
ListView. This is clearly documented by Microsoft:
LVN_ITEMCHANGED Notification
http://msdn.microsoft.com/en-us/library/bb774845.aspx
"If a list-view control has the LVS_OWNERDATA style, and the user
selects a range of items by holding down the SHIFT key and clicking the
mouse, LVN_ITEMCHANGED notifications are not sent for each selected or
deselected item. Instead, you will receive a single LVN_ODSTATECHANGED
notification, indicating that a range of items has changed state."
The LVN_ODSTATECHANGED fires the TListView's OnDataStateChange event. You
will have to use that event to handle ranges.
> Currently, instead of just adding/removing the data for the respective
> selected/deselected items as the selection event is called, I`m having to
> go through the entire list using getnextitem and reconstructing the
> stringlist of data each time. This seems like quite an overhead with
> 16000+ items (this grows monthly by 200 or so entries)
Calling TListView.GetNextItem() triggers the OnData event for each matching
item because it returns a TListItem pointer, so the TListItem properties
have to be filled in. If your OnData event handler takes some time to look
up the item data, that will slow down the loop considerably. If you are
only interested in finding index numbers instead, then I suggest you use the
ListView_GetNextItem() macro directly instead. I find that working with API
messages directly can considerably improve performance when working with
owner-data ListViews. In this case, you could use ListView_GetNextItem() to
find the selected indexes, and then use those indexes to access your data
storage directly without going through the ListView at all.
Gambit