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 都可以「自拉」並且「互拉」, 試試多重選擇 在拖放後的項目位置的變化.