home *** CD-ROM | disk | FTP | other *** search
/ Chip 1999 June / Chip_1999-06_cd.bin / zkuste / Delphi / jak / drafile / DrgDrp.Zip / DDDEST.PAS < prev    next >
Pascal/Delphi Source File  |  1998-06-30  |  7KB  |  257 lines

  1. //===================== DRAG AND DROP DESTINATION HELPERS =====================
  2. // These components are intended to provide an easy way to implement drag and
  3. // drop of files into a Delphi application.
  4. //
  5. // TDnDRun     - items which have been dropped on the application's icon on
  6. //               either the desktop or filemanager/explorer
  7. // TDnDForm    - items dropped on a form
  8. // TDnDControl - items dropped on a control (TWinControl only)
  9. //
  10. // Each component produces the same three events:
  11. //    DnDStart  - sent before the items dropped list is sent
  12. //    DnDItem   - sent for each item dropped
  13. //    DnDFinish - sent when all items have been sent
  14. //
  15. // *Warning*  I have tested the code under Delphi 3.02 only
  16. //
  17. // Version 1.00 Grahame Marsh 16 October 1997
  18. //         1.01 GSM 27 June 98 for UNDU
  19. //
  20. // Freeware - you get it for free, I take nothing, I make no promises!
  21. //
  22. // Please feel free to contact me: gsmarsh@aol.com
  23. //
  24. //==============================================================================
  25.  
  26. unit DDDest;
  27.  
  28. interface
  29.  
  30. uses
  31.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  32.   ShellAPI, DsgnIntf;
  33.  
  34. type
  35.   TDnDStartEvent = procedure (Sender: TObject; Count, X, Y: integer) of object;
  36.   TDnDItemEvent = procedure (Sender: TObject; const Item: string) of object;
  37.  
  38.   TCustomDnD = class (TComponent)
  39.   private
  40.     FParent: THandle;
  41.     FActive: boolean;
  42.     FOnDnDStart: TDnDStartEvent;
  43.     FOnDnDItem: TDnDItemEvent;
  44.     FOnDnDFinish: TNotifyEvent;
  45.     procedure SetActive (Value : boolean);
  46.   public
  47.     property Active: boolean read FActive write SetActive;
  48.     property OnDnDStart: TDnDStartEvent read FOnDnDStart write FOnDnDStart;
  49.     property OnDnDItem: TDnDItemEvent read FOnDnDItem write FOnDnDItem;
  50.     property OnDnDFinish: TNotifyEvent read FOnDnDFinish write FOnDnDFinish;
  51.   end;
  52.  
  53.   TDnDRun = class (TCustomDnD)
  54.   protected
  55.     procedure Loaded; override;
  56.   public
  57.     procedure Execute;
  58.   published
  59.     property Active;
  60.     property OnDnDStart;
  61.     property OnDnDItem;
  62.     property OnDnDFinish;
  63.   end;
  64.  
  65.   TDnDForm = class(TCustomDnD)
  66.   private
  67.     FOldDnDefWndProc,
  68.     FNewDefWndProc: pointer;
  69.     procedure NewDefWndProc (var Msg: TMessage);
  70.   protected
  71.     procedure Loaded; override;
  72.   public
  73.     constructor Create (AOwner: TComponent); override;
  74.     destructor Destroy; override;
  75.   published
  76.     property Active;
  77.     property OnDnDStart;
  78.     property OnDnDItem;
  79.     property OnDnDFinish;
  80.   end;
  81.  
  82.   TDnDControl = class(TDnDForm)
  83.   private
  84.     FControl: TWinControl;
  85.     procedure SetControl (Value: TWinControl);
  86.   protected
  87.     procedure Loaded; override;
  88.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  89.   published
  90.     property Control: TWinControl read FControl write SetControl;
  91.   end;
  92.  
  93. function DroppedCount (DropHandle: hDrop): integer;
  94. function DroppedItem (DropHandle: hDrop; Item: integer): string;
  95.  
  96. procedure Register;
  97.  
  98. implementation
  99.  
  100. //=== UTILITIES ================================================================
  101.  
  102. //--- function to return the number of items dropped given a drop handle
  103. function DroppedCount (DropHandle: hDrop): integer;
  104. begin
  105.   Result := DragQueryFile (DropHandle, -1, nil, 0)
  106. end;
  107.  
  108. //--- function to return an individual dropped item as a string, given the
  109. //    drop handle and an index to an item
  110. function DroppedItem (DropHandle: hDrop; Item: integer): string;
  111. begin
  112.   SetLength (Result, MAX_PATH);
  113.   DragQueryFile (DropHandle, Item, pchar(Result), MAX_PATH-1);
  114.   SetLength (Result, StrLen(pchar(Result)))
  115. end;
  116.  
  117. procedure TCustomDnD.SetActive (Value : boolean);
  118. begin
  119.   if Value <> FActive then
  120.   begin
  121.     FActive := Value;
  122.     if FParent <> 0 then
  123.       DragAcceptFiles (FParent, FActive)
  124.   end
  125. end;
  126.  
  127. //=== DROPPED ON RUN ===========================================================
  128.  
  129. // Dropped on application or in run parameter list so use the standard ParamCount
  130. // and ParamStr() functions to invoke the events.  OnDnDStart returns 0, 0 for
  131. // the X, Y point
  132.  
  133. procedure TDnDRun.Execute;
  134. var
  135.   Loop: integer;
  136. begin
  137.   if FActive and (ParamCount > 0) then
  138.   begin
  139.     if Assigned (FOnDnDStart) then
  140.       FOnDnDStart (Self, ParamCount, 0, 0);
  141.  
  142.     if Assigned (FOnDnDItem) then
  143.       for Loop := 1 to ParamCount do
  144.         FOnDnDItem (Self, ParamStr (Loop));
  145.  
  146.     if Assigned (FOnDnDFinish) then
  147.       FOnDnDFinish (Self)
  148.   end
  149. end;
  150.  
  151. procedure TDnDRun.Loaded;
  152. begin
  153.   inherited Loaded;
  154.   Execute
  155. end;
  156.  
  157. //=== DROPPED ON FORM ==========================================================
  158. // Put a window subclass in so that we can watch for the WM_DROPFILES message.
  159.  
  160. constructor TDnDForm.Create (AOwner: TComponent);
  161. begin
  162.   inherited Create (AOwner);
  163.   FParent := (AOwner as TForm).Handle;
  164.   FNewDefWndProc := MakeObjectInstance (NewDefWndProc)
  165. end;
  166.  
  167. procedure TDnDForm.Loaded;
  168. begin
  169.   inherited Loaded;
  170.   FOldDnDefWndProc := pointer (SetWindowLong (FParent, GWL_WndProc, longint(FNewDefWndProc)));
  171.   DragAcceptFiles (FParent, FActive)
  172. end;
  173.  
  174. destructor TDnDForm.Destroy;
  175. begin
  176.   SetWindowLong (FParent, GWL_WndProc, longint(FOldDnDefWndProc));
  177.   FreeObjectInstance (FNewDefWndProc);
  178.   inherited Destroy
  179. end;
  180.  
  181. procedure TDnDForm.NewDefWndProc (var Msg: TMessage);
  182. var
  183.   Loop,
  184.   Count: integer;
  185.   Point: TPoint;
  186. begin
  187.   with TWMDropFiles (Msg) do
  188.     if Msg = WM_DropFiles then
  189.     begin
  190. // send OnStart with count and drop coords
  191.       DragQueryPoint (Drop, Point);
  192.       Count:= DroppedCount (Drop);
  193.       if Assigned (FOnDnDStart) then
  194.         FOnDnDStart (Self, Count, Point.X, Point.Y);
  195. // send each item
  196.       if Assigned (FOnDnDItem) then
  197.         for Loop:= 0 to Count - 1 do
  198.           FOnDnDItem (Self, DroppedItem (Drop, Loop));
  199. // send finished
  200.       DragFinish (Drop);
  201.       if Assigned (FOnDnDFinish) then
  202.         FOnDnDFinish (Self);
  203.  
  204.       Result := 0;
  205.       exit
  206.     end else
  207. // if window is to be destroyed then stop drag files
  208.       if Msg = WM_Destroy then
  209.         Active := false;
  210.  
  211.   with Msg do
  212.     Result := CallWindowProc (FOldDnDefWndProc, FParent, Msg, wParam, lParam)
  213. end;
  214.  
  215. //=== DROPPED ON A TWinControl =================================================
  216.  
  217. procedure TDnDControl.Loaded;
  218. begin
  219.   if Assigned (FControl) then
  220.     FParent := FControl.Handle;   // replace form handle with control's handle
  221.                                   // if no control then will use the form's handle
  222.   inherited Loaded                // before!! calling the inherited Loaded
  223. end;
  224.  
  225. procedure TDnDControl.SetControl (Value: TWinControl);
  226. var
  227.   OldActive : boolean;
  228. begin
  229.   OldActive := FActive;
  230.   Active := false;
  231.   FControl := Value;
  232.   if Assigned (FControl) then
  233.   begin
  234.     FControl.FreeNotification (Self);
  235.     if Assigned (FControl) then
  236.       FParent := FControl.Handle;
  237.     Active := OldActive
  238.   end
  239. end;
  240.  
  241. procedure TDnDControl.Notification(AComponent: TComponent; Operation: TOperation);
  242. begin
  243.   inherited Notification (AComponent, Operation);
  244.   if (Operation = opRemove) and (AComponent = FControl) then
  245.     FControl := nil
  246. end;
  247.  
  248. //=== REGISTER COMPONENTS ======================================================
  249.  
  250. procedure Register;
  251. begin
  252.   RegisterComponents ('My Controls', [TDnDRun, TDnDForm, TDnDControl])
  253. end;
  254.  
  255. end.
  256.  
  257.