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.

