Table of Contents
Introdução
Nesse post iremos ver um exemplo de uso dos eventos de Drag and Drop (arrasta e solta) do Delphi. Drag and Drop – Kaban – em Delphi. Esse exemplo poderá ser utilizado para criar um quadro tipo Kanban, que pode ser utilizado para organizar a fazeres do dia a dia ou do trabalho.
Explorando a Propriedade DragMode e os Eventos OnDragDrop e OnDragOver no Delphi
O Delphi é uma ferramenta poderosa para o desenvolvimento de aplicações ricas e interativas, e um dos recursos mais úteis para criar interfaces dinâmicas é o suporte a drag-and-drop. Este recurso permite que os usuários arrastem objetos ou dados de uma parte da aplicação para outra, oferecendo maior interatividade e flexibilidade. Neste artigo, vamos explorar como usar a propriedade DragMode e os eventos OnDragDrop e OnDragOver no Delphi.
Entendendo a Propriedade DragMode
No Delphi, a propriedade DragMode é usada em conjunto com o mecanismo de arrastar e soltar. Ela define o comportamento do componente ao receber um item durante a operação de drag-and-drop. Normalmente, você configurará a propriedade DragMode de um componente para dmAutomatic ou dmManual, o que determina se ele responderá automaticamente ou exigirá intervenção do desenvolvedor.
- dmAutomatic: O componente entra automaticamente no modo de arrastar quando o usuário inicia uma operação de drag-and-drop.
- dmManual: Exige que você inicie explicitamente a operação usando o método
BeginDrag
.
Evento OnDragOver
O evento OnDragOver é acionado continuamente enquanto o usuário arrasta um item sobre o componente. Ele é usado para validar se o destino aceita ou não o item que está sendo arrastado.
Estrutura do Evento
procedure(Sender: TObject; Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean) of object;
- Sender: O componente que está recebendo o evento.
- Source: O componente que iniciou a operação de arrastar.
- X, Y: Coordenadas do ponteiro do mouse no momento.
- State: O estado atual do arraste (dsDragEnter, dsDragLeave, dsDragMove).
- Accept: Um valor booleano que indica se o componente aceita o item arrastado.
Exemplo de Uso
No exemplo abaixo, o componente destino aceita apenas objetos arrastados de um componente específico:
procedure TForm1.Panel1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := Source is TButton; // Aceita apenas botões end;
Evento OnDragDrop
O evento OnDragDrop é acionado quando o usuário solta o objeto arrastado sobre o componente. Aqui você implementa a lógica para manipular o item que foi arrastado e definir como ele será tratado.
Estrutura do Evento
procedure(Sender: TObject; Source: TObject; X, Y: Integer) of object;
- Sender: O componente que está recebendo o evento.
- Source: O componente que iniciou o arraste.
- X, Y: Coordenadas do mouse no momento em que o item é solto.
Exemplo de Uso
No exemplo abaixo, um botão é movido para um novo painel quando solto:
procedure TForm1.Panel1DragDrop(Sender, Source: TObject; X, Y: Integer); begin if Source is TButton then begin TButton(Source).Parent := TPanel(Sender); // Move o botão para o novo painel TButton(Source).Left := X; TButton(Source).Top := Y; end; end;
Passo a Passo: Implementando Drag-and-Drop no Delphi
No exemplo abaixo iremos demonstrar como mover painéis de um lado para o outro, como se fosse um Kanban.
- Arraste 5 painéis(TPanel) para o form principal. Três painéis serão utilizados como containers e dois painéis serão utilizados como tarefas.
- Configuração do Componente de Origem:
- Defina a propriedade DragMode como dmAutomatic.
- Adicione eventos de suporte, como
OnMouseDown
para iniciar o arraste se estiver usando dmManual.
3. Configuração do Componente de Destino:
- Adicione o evento OnDragOver para validar se o objeto pode ser solto.
- Adicione o evento OnDragDrop para manipular a lógica de soltar o item.
4. Implementação no Código: Configure os eventos no código ou no Object Inspector.
Código Completo
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls; type TForm1 = class(TForm) Panel1: TPanel; pnlToDo: TPanel; pnlTask1: TPanel; pnlTask2: TPanel; pnlInProgress: TPanel; pnlDone: TPanel; procedure FormCreate(Sender: TObject); procedure panelContainerDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); procedure panelContainerDragDrop(Sender, Source: TObject; X, Y: Integer); procedure panelTaskDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); private FDraggingPanel: TPanel; procedure InitializeKanban; public end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin InitializeKanban; end; procedure TForm1.InitializeKanban; begin // Configuração inicial dos painéis que servirão de containers pnlToDo.Caption := 'To Do'; pnlInProgress.Caption := 'In Progress'; pnlDone.Caption := 'Done'; // Configuração inicial dos painéis de tarefas pnlTask1.Caption := 'Task 1'; pnlTask2.Caption := 'Task 2'; //Configurar os painéis para o modo de arrasto automático pnlTask1.DragMode := TDragMode.dmAutomatic; pnlTask2.DragMode := TDragMode.dmAutomatic; pnlToDo.DragMode := TDragMode.dmAutomatic; pnlInProgress.DragMode := TDragMode.dmAutomatic; pnlDone.DragMode := TDragMode.dmAutomatic; //Configurar os eventos de arrastar sobre dos painéis pnlTask1.OnDragOver := panelTaskDragOver; pnlTask2.OnDragOver := panelTaskDragOver; pnlToDo.OnDragOver := panelContainerDragOver; pnlInProgress.OnDragOver := panelContainerDragOver; pnlDone.OnDragOver := panelContainerDragOver; //Configurar os eventos de arrastar e soltar dos painéis pnlToDo.OnDragDrop := panelContainerDragDrop; pnlInProgress.OnDragDrop := panelContainerDragDrop; pnlDone.OnDragDrop := panelContainerDragDrop; end; procedure TForm1.panelContainerDragDrop(Sender, Source: TObject; X, Y: Integer); begin FDraggingPanel.Align := alBottom; //configura o painel para se alinhar no fundo - essa configuração fará com que as tarefas fiquem ordenadas uma embaixo da outra, ao arrastar FDraggingPanel.Parent := TPanel(Sender); //configura o novo pai do painel tarefa FDraggingPanel.Align := alTop; //configura o painel para se alinhar ao topo - essa configuração fará com que as tarefas fiquem ordenadas uma embaixo da outra, ao arrastar FDraggingPanel := nil //Limpa a variável que recebe o painel que representa a tarefa. end; procedure TForm1.panelContainerDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := (Sender is TPanel); //Configura os painéis que serão os containers para aceitar outros painéis end; procedure TForm1.panelTaskDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin if Sender is TPanel then begin FDraggingPanel := TPanel(Sender); //Seta a variável FDraggingPanel para receber o painel que representa a tarefa. end; end; end.
Para ver o funcionamento basta clicar em cima dos painéis “Task 1” ou “Task 2” e arrastar e soltar para os painéis “To Do”, “In Progress” ou “Done”.
Veja abaixo a ilustração do projeto:
Código fonte do exemplo
Você pode fazer o download do exemplo do projeto através do repositório do github:
https://github.com/Gisele-de-Melo/Drag-and-Drop
Dicas Práticas
- Validação no OnDragOver: Use o parâmetro
Accept
para evitar comportamentos inesperados, validando os componentes que podem ser arrastados. - Organização Visual: Ao soltar o item, ajuste sua posição para evitar sobreposição ou desalinhamento.
- Customização: Combine drag-and-drop com efeitos visuais, como mudanças na cor do componente destino ao aceitar um objeto.
Conclusão
Os eventos OnDragOver e OnDragDrop oferecem uma base poderosa para implementar interatividade no Delphi, permitindo criar interfaces intuitivas e dinâmicas. Seja para construir um Kanban, um editor visual ou qualquer aplicação que requeira movimentação de componentes, o suporte a drag-and-drop no Delphi é uma solução elegante e eficaz.
Com essas dicas e exemplos, você está pronto para explorar ainda mais o potencial dessa funcionalidade e criar aplicações ricas em funcionalidades para seus usuários.