我有一个TListBox,multiselect和ExtendedSelect都设置为true。我需要能够在列表框中拖动多个项目来重新排列它们。我的问题是当用户点击已经选择的项目而没有按住CTRL或SHIFT键时会发生什么。
案例1:DragMode设置为dmManual 在鼠标按下之前清除选择。这不允许拖动多个项目。
案例2:DragMode设置为dmAutomatic MouseDown事件永远不会触发。选择未清除,因此拖动正常,但用户无法通过单击其中一个选定项目来清除选择。如果选择了所有项目或者用户想要选择的下一个项目是当前选择的一部分,这确实会导致问题。
请注意,只有在OnStartDrag过程中为DragObject指定了某些内容时,才会出现此问题。如果OnStartDrag只在用户移动鼠标后启动,我认为问题就会消失。我有Mouse.DragImmediate:= false设置,但是当我点击列表框中的项目时,我仍然会触发StartDrag。
我正在使用Delphi 7进行此项目,但我在Delphi 2007中看到了相同的行为。
答案 0 :(得分:0)
我已经玩了一段时间了。并观察相同的效果。
我会使用Case2并在列表中添加一个(全选/取消全选)按钮。它甚至可以添加额外的功能并解决问题中最烦人的部分。
答案 1 :(得分:0)
我不确定为什么会有所不同但是如果我将DragObject更改为TDrag 控制 ObjectEx(而不是TDragObjectEx),我会得到我正在寻找的行为。拖动模式设置为自动。
我试着看看这会影响到什么,但我无法理解。
答案 2 :(得分:0)
使用案例2并在TListBox.OnMouseUp事件触发时检查是否已选择并拖动了多个项目。如果选择了多个项目但未拖动,则取消选择除所单击项目之外的所有项目。
我会使用此方法,因为Windows资源管理器以这种方式工作。
答案 3 :(得分:0)
有点像kludge,但这有效。 ListBox上的DragMode设置为dmAutomatic。
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
iDropIdx, i: Integer;
pDropPoint: TPoint;
slSelected: TStrings;
begin
{Which item is being dropped onto?}
pDropPoint := Point(X, Y);
iDropIdx := ListBox1.ItemAtPos(pDropPoint, False);
slSelected := TStringList.Create;
try
{Copy the selected items to another string list}
for i := 0 to Pred(ListBox1.Items.Count) do
begin
if (ListBox1.Selected[i]) then
slSelected.Append(ListBox1.Items[i]);
end;
{Find the selected items in the listbox and swap them with the drop target}
for i := 0 to Pred(slSelected.Count) do
begin
ListBox1.Items.Exchange(ListBox1.Items.IndexOf(slSelected[i]), iDropIdx);
inc(iDropIdx);
end;
finally
slSelected.Free;
end;
end;