Delphi列表框拖放多个项目

时间:2012-02-07 12:59:25

标签: delphi drag-and-drop listbox delphi-xe

我需要在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; 

from here
它工作正常但我需要实现的是这样的 enter image description here

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

有关如何实现这一目标的任何意见表示赞赏 如果可以使用其他组件,也可以建议使用其他组件。

1 个答案:

答案 0 :(得分:6)

这样做起来非常棘手(请参阅我对此答案的第一次修订以获取错误的示例)。

这是一个通过以下方式解决问题的相当容易理解的方法:

  1. 从列表中删除所有选定的项目并将其存储在临时字符串列表中。
  2. 将项目重新添加到从目标索引开始的列表中。
  3. 重新选择每个重新添加的项目。
  4. 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的一系列调用来完成此操作,但很难做到正确。每次移动时,所选项目的所有索引都会发生变化。我上面给出的方法是我解决这个问题的首选方法。顺便说一下,我最近在树视图的上下文中处理了完全相同的问题,而且它也非常棘手!