Delphi列表框拖放多个项目

6

我需要在我的Tlistbox中拖放多个项目。
我参考的代码是:

var 
   StartingPoint : TPoint;

implementation

...

procedure TForm1.FormCreate(Sender: TObject) ;
begin
   ListBox1.DragMode := dmAutomatic;
end;

procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer) ;
var
   DropPosition, StartPosition: Integer;
   DropPoint: TPoint;
begin
   DropPoint.X := X;
   DropPoint.Y := Y;
   with Source as TListBox do
   begin
     StartPosition := ItemAtPos(StartingPoint,True) ;
     DropPosition := ItemAtPos(DropPoint,True) ;

    Items.Move(StartPosition, DropPosition) ;
   end;
end;

procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer; State:  TDragState; var Accept: Boolean) ;
begin
    Accept := Source = ListBox1;
end;

procedure TForm1.ListBox1MouseDown(Sender: TObject; Button: TMouseButton;
   Shift: TShiftState; X, Y: Integer) ;
begin
    StartingPoint.X := X;
    StartingPoint.Y := Y;
end; 

从这里开始。
它可以正常工作,但我需要实现的是像这样的效果 enter image description here

我想要这样做的原因是因为有一个与这些列表框项目相对应的特定顺序。 因此,我想启用多个拖放而不仅仅是手动选择每个项目并拖放它。

欢迎提出任何关于如何实现这一点的看法。
如果可能的话,还可以建议使用其他组件。

1个回答

9
这其实是一个棘手的问题(请参见我对此答案的第一次修订,以了解如何出错)。
下面是一种相当易于理解的方法,通过以下步骤解决该问题:
1. 从列表中删除所有选定的项目,并将它们存储在一个临时字符串列表中。 2. 从目标索引开始重新添加项目到列表中。 3. 重新选择每个重新添加的项目。
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  ListBox: TListBox;
  i, TargetIndex: Integer;
  SelectedItems: TStringList;
begin
  Assert(Source=Sender);
  ListBox := Sender as TListBox;
  TargetIndex := ListBox.ItemAtPos(Point(X, Y), False);
  if TargetIndex<>-1 then
  begin
    SelectedItems := TStringList.Create;
    try
      ListBox.Items.BeginUpdate;
      try
        for i := ListBox.Items.Count-1 downto 0 do
        begin
          if ListBox.Selected[i] then
          begin
            SelectedItems.AddObject(ListBox.Items[i], ListBox.Items.Objects[i]);
            ListBox.Items.Delete(i);
            if i<TargetIndex then
              dec(TargetIndex);
          end;
        end;

        for i := SelectedItems.Count-1 downto 0 do
        begin
          ListBox.Items.InsertObject(TargetIndex, SelectedItems[i], SelectedItems.Objects[i]);
          ListBox.Selected[TargetIndex] := True;
          inc(TargetIndex);
        end;
      finally
        ListBox.Items.EndUpdate;
      end;
    finally
      SelectedItems.Free;
    end;
  end;
end;

现在,可以通过一系列调用Move来实现此操作,但很难做到正确。每次移动所选项目时,所有索引都会改变。我上面提供的方法是解决这个问题的首选方法。顺便说一句,我最近在树视图的背景下解决了完全相同的问题,那里也很棘手!

1
您正在使用先前版本的代码。现在已修复了错误。就像我所说的那样,这个问题出奇地棘手! - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接