Pregunta

Tengo un TListBox con multiselección y ExtendedSelect ambos configurados en verdadero. Necesito poder arrastrar varios elementos en el cuadro de lista para reorganizarlos. Mi problema es lo que sucede cuando el usuario hace clic en un elemento que ya está seleccionado sin mantener presionada la tecla CTRL o MAYÚS.

Caso 1: DragMode está establecido en dmManual La selección se borra antes de presionar el mouse. Esto no permitirá arrastrar varios elementos.

Caso 2: DragMode está configurado en dmAutomatic El evento MouseDown nunca se activa. La selección no se borra, por lo que arrastrar está bien, pero el usuario no puede borrar la selección haciendo clic en uno de los elementos seleccionados. Esto realmente causa un problema si todos los elementos están seleccionados o si el siguiente elemento que el usuario desea seleccionar era parte de la selección actual.

Tenga en cuenta que este problema solo ocurre si asigna algo al DragObject en el procedimiento OnStartDrag. Creo que el problema desaparecería si OnStartDrag solo comenzara después de que el usuario mueva el mouse. Tengo Mouse.DragImmediate: = false configurado, pero sigo disparando el StartDrag tan pronto como hago clic en un elemento en el cuadro de lista.

Estoy usando Delphi 7 para este proyecto pero veo el mismo comportamiento en Delphi 2007.

¿Fue útil?

Solución 4

No estoy seguro de por qué esto hace la diferencia, pero si cambio el DragObject para que sea un TDrag Control ObjectEx (en lugar de un TDragObjectEx) obtengo el comportamiento que estoy buscando. El modo de arrastre está configurado en Automático.

Traté de mirar y ver lo que esto estaba afectando, pero no pude resolverlo.

Otros consejos

He jugado con esto por un tiempo. Y observe los mismos efectos.

Usaría Case2 y agregaría un botón (Seleccionar todo / Deseleccionar todo) a la lista. Incluso agrega funcionalidad adicional y resuelve la parte más molesta del problema.

Use el Caso 2 y cuando se active el evento TListBox.OnMouseUp, verifique si se seleccionaron y arrastraron varios elementos. Si se seleccionaron varios elementos, pero no se arrastraron, anule la selección de todos los elementos aparte del elemento seleccionado.

Usaría este método porque Windows Explorer funciona de esta manera.

Un poco difícil pero esto funciona. DragMode en ListBox está configurado en 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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top