Técnicas de drag-and-drop
Veja nesse artigo de Adriano Santos, como implementar o drag and drop em componentes como ListBox, Animate e DBGrid.
Um dos recursos mais utilizados no Windows certamente é o Drag-and-Drop que significa arrastar-e-soltar. Em toda minha experiência com programação vejo pouca utilização deste recurso em aplicações Delphi e muitas dúvidas em fóruns, por isso elaborei alguns exemplos para entendermos melhor como funciona este recurso.
Entendendo a lógica
O recurso de drag-and-drop é ativado partindo do evento onMouseDown do controle Origem. É nele que iniciamos a operação usando o método BeginDrag do objeto. A finalização do arrasto é controlada pelo evento onEndDrag também do objeto Origem.
No objeto Destino usamos os eventos onDragOver para descobrirmos se o Source (objeto Origem) é o objeto esperado e assim aceitar a ação. Ainda no objeto Destino, no evento onDragDrop, ou seja, quando o usuário soltar o mouse sobre o objeto, chamamos novamente o evento onEndDrag do objeto Origem passando o parâmetro True. Isso fará com que a ação seja finalizada. Vamos desenvolver um exemplo prático pra que fique mais claro.
1º Exemplo: Arrastando um TAnimate
Nosso primeiro exemplo é bastante simples. Insira um TListBox, um TPanel e dentro do TPanel um TAnimate. No TListBox insira os seguintes valores na propriedade Items:
- aviNone
- aviFindFolder
- aviFindFile
- aviFindComputer
- aviCopyFiles
- aviCopyFile
- aviRecycleFile
- aviEmptyRecycle
- aviDeleteFile
Como o componente TAnimate não possui os eventos onDragOver e onDragDrop, vamos usar o TPanel como “controlador”, ou seja, ele que receberá o arrasto e definirá o novo AVI do componente e o porá em execução.
No evento onMouseDown do ListBox (neste exemplo deu-se o nome de LstAvi) digite o algoritmo da Listagem 1. Este algoritmo verifica se o objeto (Sender) é o LstAvi e ainda se o botão esquerdo do mouse está pressionado. Em caso positivo, dá início ao processo de drag chamando o método BeginDrag.
Listagem 1. Evento onMouseDown do LstAvi (ListBox)
procedure TFrmDragDrop.LstAviMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (Sender = LstAvi) and (Button = mbLeft) then
LstAvi.BeginDrag(False); // inicia a operacao
end;
Agora vamos mexer com o nosso TPanel. Em seu evento onDragDrop vamos fazer uma simples verificação. Se o Source (objeto origem) for o LstAvi então chamamos o método EndDrag, bem simples, como mostra a Listagem 2.
Listagem 2. Evento onDragDrop do Panel
procedure TFrmDragDrop.Panel1DragDrop(Sender, Source: TObject; X,
Y: Integer);
begin
if Source = LstAvi then
LstAvi.EndDrag(True); // finaliza o processo
end;
Ainda no TPanel, porém agora no evento onDragOver, faremos outra verificação para aceitar ou não a ação. Se o objeto Origem (Source) for LstAvi então aceitamos: Accept := True, como mostra a Listagem 3.
Listagem 3. Evento onDragOver do Panel
procedure TFrmDragDrop.Panel1DragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
begin
if Source = LstAvi then
Accept := True; // aceita a ação
end;
Pra finalizar este primeiro exemplo, basta programarmos o evento onEndDrag do LstAvi fazendo com que o mesmo mude o avi do TAnimate e ative-o.
Para isso verificamos se o alvo (Target) é diferente de Nil, nos informando que houve uma chamada ao evento por outro componente, assim sendo comandamos as ações que trocam o avi e ativam-o. Veja como fica na Listagem 4.
Listagem 4. Evento onEndDrag do LstAvi
procedure TFrmDragDrop.LstAviEndDrag(Sender, Target: TObject; X,
Y: Integer);
begin
if Target <> nil then
begin
if Animate1.CommonAVI <> aviNone then
Animate1.Stop;
Animate1.CommonAVI := TCommonAVI(LstAvi.ItemIndex);
if Animate1.CommonAVI <> aviNone then
Animate1.Play(Animate1.StartFrame, Animate1.StopFrame, 0);
end;
end;
2º Exemplo: Trocando itens entre ListBox
Nosso segundo exemplo é um pouco mais trabalhoso, mas segue a mesma lógica aplicada no exemplo anterior. Vamos “trocar” de lugar os itens de dois ListBox, ou seja, poderemos arrasta-los de um lado para o outro.
Para este exemplo precisaremos apenas de dois listbox em tela com os nomes de ListaOrigem e ListaDestino.
Em cada listbox usaremos os eventos onMouseDown, onEndDrag, onDragOver e onDragDrop. Pra facilitar nossa vida, faremos um typecast nos eventos para identificar quem está sendo Origem e Destino em cada evento, desviando desta forma nosso fluxo de programação tornando os eventos genéricos.
Começaremos pelo ListaOrigem no evento onMouseDown. A dica é simples: basta verificar se o Sender é o ListaOrigem ou ListaDestino e assim chamar o método BeginDrag do TListBox, como mostra a Listagem 5.
Listagem 5. Evento onMouseDown do ListaOrigem (ListBox)
procedure TFrmDragDrop.ListaOrigemMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (Button = mbLeft) and ((Sender = ListaOrigem) or (Sender = ListaDestino)) then
TListBox(Sender).BeginDrag(False) // inicia a operacao
end;
No evento onDragOver da ListaOrigem faremos o “aceite” da ação, como mostra a Listagem 6.
Listagem 6. Evento onDragOver
procedure TFrmDragDrop.Panel1DragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
begin
if (Source = ListaOrigem) or (Source = ListaDestino) then
Accept := True
end;
Seguindo a mesma linha de raciocínio chamamos o método EndDrag no evento onDragDrop, como mostra aListagem 7.
Listagem 7. Evento onDragDrop
procedure TFrmDragDrop.Panel1DragDrop(Sender, Source: TObject; X,
Y: Integer);
begin
if (Source = ListaOrigem) or (Source = ListaDestino) then
TListBox(Sender).EndDrag(True);
end;
Pra fechar o segundo exemplo basta agora programar a parte mais importante, o evento onEndDrag. Neste caso basta verificar se o alvo é diferente de Nil e então usar o método MoveSelection do componente TListBox, assim como mostra a Listagem 8.
Listagem 8. Evento onEndDrag
procedure TFrmDragDrop.LstAviEndDrag(Sender, Target: TObject; X,
Y: Integer);
begin
if Target <> nil then
// trata o fim de uma operacao que foi aceita
TListbox(Sender).MoveSelection(TListBox(Target));
end;
Note que em nenhum momento trabalhamos os eventos da ListaDestino, certo? Bom, agora basta associar os eventos onMouseDown, onEndDrag, onDragOver e onDragDrop do ListaDestino aos respectivos eventos de ListaOrigem.
3º Exemplo: Drag-and-drop X DBGrid
Para treinarmos ainda mais o recurso este terceiro exemplo mostra como usar o drag-and-drop com DBGrid. Vamos “trazer” o título da coluna do dbgrid para um Edit.
Precisaremos de: um DBGrid, um Table, um DataSource e um Edit. Ligue o Table da tabela Animals do aliás DBDEMOS. Ligue também o DataSource e o DBGrid.
A programação segue a mesma linha anterior, portanto não entrarei em detalhes. A listagem 9 mostra os eventos onMouseDown e onEndDrag do DBGrid e também onDragDrop e onDragOver do Edit1.
A única alteração em relação aos dois últimos exemplos é que precisamos pegar o título da coluna que o usuário arrastou para o Edit1. Para isso declare a variável Titulo pública para que possamos enxergá-la em toda unit (Listagem 10).
No evento onTitleClick do DBGrid atualizamos a variável Titulo com o nome da coluna. (Listagem 11).
Listagem 10. Eventos do DBGrid
procedure TFrmDragDrop.DBGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (Sender = DbGrid1) and (Button = mbLeft) then
DbGrid1.BeginDrag(False); // inicia a operacao<
end;
procedure TFrmDragDrop.DBGrid1EndDrag(Sender, Target: TObject; X,
Y: Integer);
begin
if Target <> nil then
Edit1.Text := Titulo;
end;
procedure TFrmDragDrop.Edit1DragDrop(Sender, Source: TObject; X,
Y: Integer);
begin
if Source = DbGrid1 then
DbGrid1.EndDrag(True); // comanda o final da operacao
end;
procedure TFrmDragDrop.Edit1DragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
begin
if Source = DbGrid1 then
Accept := True; // aceita se vier da lista
end;
Listagem 11. Evento onTitleClick do DBGrid
procedure TFrmDragDrop.DBGrid1TitleClick(Column: TColumn);
begin
Titulo := Column.FieldName;
end;
Bem, com isso finalizamos esta bateria de exemplos sobre Drag-and-drop.
Conclusões
Nestes exemplos vimos como é fácil trabalhar com um dos recursos mais utilizados nas interfaces para Windows. O drag-and-drop é útil em diversas ocasiões e ajuda na produtividade do sistema.
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo