Delphi 的 FieldEditor 及 Tab Order Editor 的 ListBox 可以將各項目以
Drag & Drop 的方式掉換位置, 如何實作?
以下的做法可以讓 ListBox 既可以掉換自己的項目順序,
也可以接受來自別的 ListBox 拖拉過來的項目:
1. 放兩個 TListBox 在 Form 上, 分別為 ListBox1 與 ListBox2
2. 分別為兩個 ListBox 建立不同的項目 (Items屬性)
3. 兩個 ListBox 有相同的的屬性與事件:
MultiSelect := true; // 允許多重選擇拖拉
DragMode := dmAutomatic;
OnDragOver := ListBox1DragOver; // ListBox2 的OnDrapOver事件也指向此
OnDragDrop := ListBox1DragDrop; // ListBox2 的OnDrapDrop事件也指向此
4. 撰寫下列程式碼:
procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
// 如果要只接受自己拖拉, 下面這行改成 Accept := (Sender = Source);
Accept := true;
end;
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
lbSource, lbTarget: TListBox;
i: integer;
InsPos: integer;
begin
if (not (Source is TListBox)) or (not (Sender is TListBox)) then
Exit;
lbSource := TListBox(Source);
lbTarget := TListBox(Sender);
if lbSource = lbTarget then // 來源與目的相同=>在自己的範圍內拖拉
begin
InsPos := lbTarget.ItemAtPos(Point(x,y), true);
for i := 0 to lbSource.Items.Count-1 do
begin
if lbSource.Selected[i] then
begin
lbTarget.Items.Move(i, InsPos);
Inc(InsPos);
end;
end;
end
else // 來源與目的不同=>從別的物件中拖拉過來
begin
i := 0;
while i < lbSource.Items.Count do // 不要用 for...do 迴圈!!!
begin
if lbSource.Selected[i] then
begin
lbTarget.Items.Add(lbSource.Items.Strings[i]);
lbSource.Items.Delete(i);
end
else
Inc(i);
end; // of while
end;
end;
5. 執行, 試試看是否兩個 ListBox 都可以「自拉」並且「互拉」, 試試多重選擇
在拖放後的項目位置的變化.
               (
geocities.com/huanlin_tsai)