Pergunta

Eu tenho um TListBox com multiselect e ExtendedSelect ambos conjunto para true. Eu preciso ser capaz de arrastar vários itens na caixa de lista para re-organizar-los. Meu problema é o que acontece quando o usuário clica em um item que já está selecionados sem mantendo pressionada a tecla CTRL ou SHIFT.

Caso 1: DragMode está definida para dmManual A seleção é limpa antes do baixo mouse. Isso não vai permitir que vários itens a ser arrastado.

Caso 2: DragMode está definida para dmAutomatic O evento MouseDown nunca dispara. A seleção não é limpo por isso arrastando é OK, mas o usuário não pode limpar a seleção clicando em um dos itens selecionados. Isso realmente causa um problema se todos os itens estão selecionados ou o próximo item que o usuário deseja selecionar fez parte da seleção atual.

Note que este problema só acontece se você atribuir algo para o DragObject no procedimento OnStartDrag. Acho que o problema iria embora se OnStartDrag só iria começar depois que o usuário move o mouse. Eu tenho Mouse.DragImmediate: = false set, mas eu ainda obter o startDrag disparou assim que eu clicar em um item na caixa de listagem

.

Eu estou usando Delphi 7 para este projeto, mas eu vejo o mesmo comportamento em Delphi 2007.

Foi útil?

Solução 4

Eu não sei por que isso faz a diferença, mas se eu mudar o DragObject ser um TDrag Controle ObjectEx (em vez de um TDragObjectEx) recebo o comportamento que eu estou procurando. modo de arrastar será definido como Automático.

Eu tentei olhar e ver o que isso estava afetando, mas eu não conseguia entender.

Outras dicas

Eu tenho jogado com isso por um tempo. E observar os mesmos efeitos.

Gostaria de usar Case2 e adicionar um botão (Selecionar Tudo / Desmarcar Tudo) à lista. Ele ainda acrescenta funcionalidade extra e resolve a parte mais chata do problema.

Caso de Uso 2 e quando o evento é acionado TListBox.OnMouseUp verificar para ver se vários itens são selecionados e foram arrastados. Se vários itens são selecionados, mas não foram arrastados, em seguida, desmarque todos os itens além do item clicado.

Gostaria de usar este método porque o Windows Explorer funciona desta forma.

Um pouco de um truque, mas isso funciona. DragMode na caixa de listagem é definida para 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top