VIII. Code complet du composant TDropImage▲
DropImg.pas
Sélectionnez
unit DropImg;
interface
uses
  Windows, SysUtils, Classes, Controls, ExtCtrls;
type
  TDropEvent = procedure(Sender : TObject; X, Y : integer) of object;
  TDropImage = class(TImage)
  private
    FClone : TImage;
    FDropControl : TControl;
    FOnDrop : TDropEvent;
    procedure SetDropControl(New : TControl);
    procedure CalcClonePos(X, Y : integer);
  protected
    procedure Notification(AComponent : TComponent; Operation : TOperation); override;
    procedure MouseDown(Button : TMouseButton; Shift : TShiftState; X, Y : integer); override;
    procedure MouseMove(Shift : TShiftState; X, Y : integer); override;
    procedure MouseUp(Button : TMouseButton; Shift : TShiftState; X, Y : integer); override;
  public
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
  published
    property DropControl : TControl read FDropControl write SetDropControl;
    property OnDrop : TDropEvent read FOnDrop write FOnDrop;
  end;
implementation
constructor TDropImage.Create(AOwner : TComponent);
begin
  inherited;
  FClone := nil;
  FDropControl := nil;
  FOnDrop := nil;
end;
destructor TDropImage.Destroy;
begin
  DropControl := nil;
  if FClone <> nil then
    FClone.Free;
  inherited;
end;
procedure TDropImage.SetDropControl(New : TControl);
begin
  if New = FDropControl then exit;
  if Assigned(FDropControl) and (not (csDestroying in FDropControl.ComponentState)) then
    FDropControl.RemoveFreeNotification(Self);
  FDropControl := New;
  if Assigned(FDropControl) then
    FDropControl.FreeNotification(Self);
end;
procedure TDropImage.CalcClonePos(X, Y : integer);
var Pt : TPoint;
begin
  Pt := ClientToParent(Point(X, Y));
  FClone.Left := Pt.X - Width  div 2;
  FClone.Top  := Pt.Y - Height div 2;
end;
procedure TDropImage.Notification(AComponent : TComponent; Operation : TOperation);
begin
  if (AComponent = FDropControl) and (Operation = opRemove) then
    FDropControl := nil;
end;
procedure TDropImage.MouseDown(Button : TMouseButton; Shift : TShiftState; X, Y : integer);
begin
  inherited;
  if (not Enabled) or (Button <> mbLeft) then exit;
  if FClone <> nil then // par précaution, mais ne devrait jamais arriver
    FClone.Free;
  // Création du clone
  FClone := TImage.Create(Self);
  FClone.Parent := Parent;
  FClone.Width := Width;
  FClone.Height := Height;
  FClone.Stretch := Stretch;
  FClone.Picture.Assign(Picture);
  // Calcul de la position initiale du clone
  CalcClonePos(X, Y);
end;
procedure TDropImage.MouseMove(Shift : TShiftState; X, Y : integer);
begin
  inherited;
  if FClone <> nil then
    CalcClonePos(X, Y);
end;
procedure TDropImage.MouseUp(Button : TMouseButton; Shift : TShiftState; X, Y : integer);
var Pt : TPoint;
begin
  inherited;
  if FClone = nil then exit;
  // Destruction du clone
  FreeAndNil(FClone);
  // Calcul des coordonnées à envoyer à l'événement OnDrop
  if not Assigned(FOnDrop) then exit;
  Pt := Point(X, Y);
  if FDropControl = nil then Pt := ClientToParent(Pt) else
  begin
    Pt := FDropControl.ScreenToClient(ClientToScreen(Pt));
    // Dans ce cas on vérifie que l'on a bien déposé sur le contrôle DropControl
    if not PtInRect(Rect(0, 0, DropControl.Width, DropControl.Height), Pt) then
      exit;
  end;
  FOnDrop(Self, Pt.X, Pt.Y);
end;
end.

