The root issue is that when you SHIFT+Click multiple items, you will NOT get any OnSelectItem
events for the items that have become selected. The SHIFT+Click causes all list view items to be unselected first, triggering a single OnSelectItem
event with Item=nil
and Selected=False
, before the new items then become selected. At the time of that event, TListView.SelCount
really is 0, so you disable your button, but then there are no further OnSelectItem
events to tell you that new items have been selected, so you do not check SelCount
again to re-enable the button.
The OnSelectItem
event is triggered in reply to the LVN_ITEMCHANGED
notification when a single item changes state between selected and unselected, or when ALL items in the entire ListView change to the same selected/unselected state. However, in virtual mode, when multiple consecutive items change to the same state at the same time, Windows can instead send a single LVN_ODSTATECHANGED
notification for that range of items. TListLiew
does not trigger OnSelectItem
when it receives LVN_ODSTATECHANGED
, it triggers OnDataStateChange
instead, eg:
procedure TForm3.ListView1DataStateChange(Sender: TObject; StartIndex, EndIndex: Integer; OldState, NewState: TItemStates);
begin
if (NewState * [isSelected]) <> (OldState * [isSelected]) then
Button1.Enabled := ListView1.SelCount > 0;
end;
So you need to use both OnSelectItem
and OnDataStateChange
to handle all possible select/unselect state changes.
The best solution is to not enable/disable the TButton
manually on individual item state changes. Drop a TActionManager
on the Form, create a new TAction
and assign it to the TButton.Action
property, and then use the TAction.OnUpdate
event to enable/disable the TAction
based on the current TListView.SelCount
, eg:
procedure TForm3.MyActionUpdate(Sender: TObject);
begin
MyAction.Enabled := ListView1.SelCount > 0;
end;
That will automatically enable/disable the associated TButton
every time the main message queue goes idle, including after ListView notification messages have been processed. This way, you can keep the TButton
updated no matter what combination of input is used to select/unselect ListView items.