2012-02-07 96 views
3

我需要拖放我的Tlistbox内的多个项目。
我这里指的是代码是德尔福listbox拖放多个项目

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

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

任何意见,我该如何实现这一点表示赞赏。
也可以建议使用其他组件,如果以下可能使用相同的。

回答

6

这是令人惊讶的棘手做好(见我这个答案的第一次修订为如何得到它错了一个例子)。

这是一个相当容易理解的方式,通过解决了这个问题:

  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要做到这一点,但它很难得到它的权利。每次您进行移动时,所选项目的所有索引都会更改。上面给出的方法是我解决这个问题的首选方法。顺便提一下,我最近在树视图的上下文中研究了完全相同的问题,在这里也非常棘手!

+0

您正在使用以前版本的代码。错误现在已修复。就像我说的,要想得到正确的令人惊讶的棘手问题! – 2012-02-07 13:39:07

+0

非常感谢! :) – Shirish11 2012-02-09 07:50:47