====== Drag & Drop avec un TControl ======
Le **Drag & Drop** est une fonctionnalité permettant de cliquer sur un élément, de le déplacer tout en maintenant le bouton de la souris enfoncé, puis de le déposer à un autre endroit. Dans Lazarus, cette fonctionnalité peut être implémentée sur des composants dérivés de **TControl**. Cet article explique comment gérer le Drag & Drop d'un **TControl**.
===== Introduction =====
La gestion du **Drag & Drop** dans Lazarus repose sur plusieurs événements et propriétés définis dans **TControl**. En comprenant et en manipulant ces événements, il est possible de permettre à un contrôle de devenir une source ou une destination de Drag & Drop.
===== Propriétés Clés =====
Les propriétés suivantes de **TControl** sont essentielles pour implémenter le **Drag & Drop** :
* **DragMode** : Cette propriété détermine si le contrôle doit commencer automatiquement une opération de Drag & Drop. Les valeurs possibles sont :
* **dmManual** : L'opération de Drag & Drop est initiée manuellement via le code.
* **dmAutomatic** : L'opération commence automatiquement lorsque l'utilisateur déplace le contrôle.
* **DragCursor** : Détermine le curseur à afficher lorsque l'utilisateur effectue une opération de Drag & Drop.
* **DragKind** : Spécifie le type de glissement. Peut être **dkDrag** (pour un glissement standard) ou **dkDock** (pour le glissement d'ancrage dans des applications plus complexes).
===== Événements Clés =====
Plusieurs événements de **TControl** permettent de gérer le **Drag & Drop** de manière personnalisée :
* **OnStartDrag** : Se déclenche lorsque le contrôle commence une opération de Drag & Drop. Cet événement permet de configurer des informations supplémentaires ou de personnaliser le comportement initial.
* **OnDragOver** : Se déclenche lorsqu'un contrôle glisse sur une cible de dépôt. Il permet de déterminer si le contrôle en cours de glissement peut être déposé sur la cible en fonction de conditions spécifiques.
* **OnDragDrop** : Se déclenche lorsque le contrôle est lâché sur une cible de dépôt. Cet événement gère ce qui se passe une fois que l'utilisateur a relâché le bouton de la souris.
* **OnEndDrag** : Se déclenche lorsque l'opération de Drag & Drop est terminée, que ce soit par un dépôt réussi ou par l'annulation de l'opération.
===== Implémentation de Base =====
Voici un exemple de code montrant comment implémenter une fonctionnalité de **Drag & Drop** simple entre deux **TControl** :
procedure TForm1.FormCreate(Sender: TObject);
begin
// Configuration initiale du contrôle source
SourceControl.DragMode := dmAutomatic;
SourceControl.DragCursor := crDrag;
// Configuration du contrôle cible pour accepter le Drag & Drop
TargetControl.OnDragOver := @TargetControlDragOver;
TargetControl.OnDragDrop := @TargetControlDragDrop;
end;
procedure TForm1.SourceControlStartDrag(Sender: TObject; var DragObject: TDragObject);
begin
// Logique personnalisée au début du drag
end;
procedure TForm1.TargetControlDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
// Vérifier si la cible accepte le contrôle source
Accept := Source is TControl; // Accepte le drag si la source est un TControl
end;
procedure TForm1.TargetControlDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
// Logique lorsque le contrôle est déposé sur la cible
ShowMessage('Contrôle déposé avec succès !');
end;
===== Explication du Code =====
* **FormCreate** : Dans cette méthode, nous configurons **SourceControl** pour qu'il commence automatiquement une opération de Drag & Drop lorsqu'il est déplacé (en définissant **DragMode** à **dmAutomatic**). Nous définissons également un curseur spécifique (**DragCursor**).
* **TargetControlDragOver** : Cet événement se déclenche continuellement pendant que l'utilisateur déplace le contrôle source sur la cible. Ici, nous définissons la variable **Accept** à **True** si la source est un **TControl**, ce qui signifie que la cible accepte le dépôt.
* **TargetControlDragDrop** : Cet événement se déclenche lorsque l'utilisateur lâche le contrôle source sur la cible. Une simple boîte de dialogue est affichée pour indiquer que l'opération a été réussie.
===== Personnalisation du Drag & Drop =====
Le Drag & Drop dans Lazarus peut être personnalisé de plusieurs façons :
* **Objets de Drag & Drop personnalisés** : En définissant la variable **DragObject** dans l'événement **OnStartDrag**, il est possible de créer des objets de glissement personnalisés qui contiennent des informations spécifiques à transmettre entre le contrôle source et le contrôle cible.
* **Validation des cibles** : L'événement **OnDragOver** peut être utilisé pour valider si un contrôle source spécifique peut être déposé sur une cible donnée, en fonction de critères tels que le type de données transportées.
* **Effets visuels** : Vous pouvez changer le curseur ou afficher des indices visuels supplémentaires pour améliorer l'expérience utilisateur pendant l'opération de Drag & Drop.
===== Cas d'Utilisation Avancés =====
* **Déplacement d'objets dans une interface graphique** : Utiliser le **Drag & Drop** pour permettre aux utilisateurs de réorganiser des objets visuels (comme des icônes ou des composants) dans une application.
* **Transfert de données** : Implémenter le **Drag & Drop** pour permettre le transfert de données d'un contrôle à un autre, par exemple, en faisant glisser des éléments d'une liste vers une autre.
==== DragOver ====
La méthode ''DragOver'' est un événement déclenché lorsque l'utilisateur fait glisser un objet sur une autre zone de l'interface utilisateur qui peut potentiellement accepter le dépôt de l'objet.
Voici une explication des paramètres de l'événement ''DragOver'' :
* **Source: TObject**
Ce paramètre fait référence à l'objet qui est en cours de glisser.\\
Il peut s'agir de n'importe quel composant ou objet que l'utilisateur a commencé à déplacer.
Source peut aussi faire référence a un ''TDragObject'' si un ''TDragObject'' (ou descendant) a été créé lors de l'appel de ''OnStartDrag''. ([[prog:lazarus:cas:draganddrop#creer_et_initialiser_le_tdragobject_dans_l_evenement_onstartdrag|Voir exemple ici]])
* **X, Y: integer**
Ces paramètres représentent les coordonnées X et Y du curseur de la souris au moment où l'événement **DragOver** est déclenché. Les coordonnées sont données par rapport au composant qui reçoit l'événement.
* **State: TDragState**
Ce paramètre indique l'état actuel de l'opération de glisser-déposer. **TDragState** peut avoir plusieurs valeurs, telles que :
* **dsDragEnter** : l'objet vient d'entrer dans la zone réceptrice.
* **dsDragLeave** : l'objet est en train de quitter la zone réceptrice.
* **dsDragMove** : l'objet est en train de se déplacer au-dessus de la zone réceptrice.
* **Accept: boolean**\\
Ce paramètre est passé par référence et est utilisé pour indiquer si la zone réceptrice accepte ou non l'objet qui est en cours de glisser. Si vous définissez **Accept** sur `True`, cela signifie que la zone réceptrice accepte le dépôt de l'objet. Si **Accept** est `False`, cela signifie que le dépôt n'est pas autorisé.
**Exemple d'utilisation :**
Supposons que vous ayez une liste (ListBox) et que vous souhaitiez permettre aux utilisateurs de déposer des éléments dans cette liste uniquement si l'élément provient d'une autre liste. Vous pourriez écrire un gestionnaire **DragOver** comme suit :
procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
// On accepte seulement les objets provenant de ListBox2
if Source is TListBox then
Accept := (Source = ListBox2)
else
Accept := False;
Case State of
dsDragEnter : // Le drag viens d'entrer sur ce Control
dsDragLeave : // Le drag viens de sortir du Control
dsDragMove : // Le drag bouge sur le Control
end;
end;
Dans cet exemple, le code vérifie si l'objet source est une **TListBox** et s'il s'agit de **ListBox2**. Si c'est le cas, le dépôt est accepté (**Accept := True**), sinon il est rejeté (**Accept := False**).
===== En résumé =====
Le **Drag & Drop** dans Lazarus est une fonctionnalité puissante et flexible, permettant aux développeurs de créer des interfaces utilisateur interactives et intuitives. En maîtrisant les propriétés et événements associés à **TControl**, vous pouvez implémenter des opérations de **Drag & Drop** simples ou complexes adaptées aux besoins de votre application.
====== Sources & Ressources ======
* [[prog:lazarus:cas:draganddrop|Drag & Drop dans Lazarus]]