Search code examples
listviewdelphidelphi-2009

How to reset the selection mark after you've changed the selection in a TListView?


I have a TListView in virtual mode and when I drag and drop an item I want to move the selection to the new item position. I do it clearing the selection and then set Selected of the desired item. It's ok, but there is a problem. After this happens if I hold shift and click a item (like multi selection) the list behaves like the start of the selection is the item that was selected before and not the one that I selected (with Selected:= True).

I tried to simulate a click, but after I move the mouse I get an access violation:

procedure TForm1.ListDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
 List.Perform(WM_LBUTTONDOWN, MK_LBUTTON, $002E001E);
 Sleep(10);
 List.Perform(WM_LBUTTONUP, 0, $002E001E);
end;

Solution

  • After selecting the new item, you should set it as focused as well. But, more importantly, you need to send the ListView a LVM_SETSELECTIONMARK message:

    The selection mark is the item index from which a multiple selection starts.

    For example:

    procedure TForm1.ListDragDrop(Sender, Source: TObject; X, Y: Integer);
    var
      Item: TListItem;
    begin
      ...
      Item := ...; // the list item after it has been moved to its new position...
      Item.Selected := True;
      Item.Focused := True;
      List.Perform(LVM_SETSELECTIONMARK, 0, Item.Index);
      List.Invalidate;
      ...
    end;