The Unofficial Newsletter of Delphi Users - by Robert
Vivrette
Drop File Helper Components
by Grahame Marsh - gsmarsh@aol.com
These simple components were written to provide an easy way for a Delphi form or individual control to receive files dropped on to it. An another component is used to retrieve files dropped onto the application's icon, from say Explorer, triggering the same events as for a form or control.
The components encapsulate a number of Win32 API calls (found in ShellAPI.pas) :
type
HDROP = Longint;
function DragQueryFile(Drop: HDROP; FileIndex: UINT; FileName: PChar;
cb: INT): INT; stdcall;
function DragQueryPoint(Drop: HDROP; var Point: TPoint): BOOL;
stdcall;
procedure DragFinish(Drop: HDROP); stdcall;
procedure DragAcceptFiles(Wnd: HWND; Accept: BOOL); stdcall;
You use the DragAcceptFiles call first to inform windows that the control will accept dropped files. When you are dragging a file over this control the cursor changes to show that the control can accept the drop. DragQueryFile is used to retrieve the filename or names, and the count of files available. DragQueryPoint returns to coordinates of the drop point. And finally, when you are finished retrieving information you call DragFinish.
The component interface looks like this:
type
TDnDStartEvent = procedure (Sender: TObject; Count, X, Y:
integer) of object;
TDnDItemEvent = procedure (Sender: TObject; const Item: string)
of object;
TCustomDnD = class (TComponent)
private
FParent: THandle;
FActive: boolean;
FOnDnDStart: TDnDStartEvent;
FOnDnDItem: TDnDItemEvent;
FOnDnDFinish: TNotifyEvent;
procedure SetActive (Value : boolean);
public
property Active: boolean read FActive write
SetActive;
property OnDnDStart: TDnDStartEvent read
FOnDnDStart write FOnDnDStart;
property OnDnDItem: TDnDItemEvent read FOnDnDItem
write FOnDnDItem;
property OnDnDFinish: TNotifyEvent read
FOnDnDFinish write FOnDnDFinish;
end;
This custom interface is never used directly, it simply contains the three events common to all of the functional drag and drop components. When files are dropped the events fire in turn - OnDnDStart, then OnDnDItem for each filename and then OnDnDFinish when all file events have been triggered. The Active property can be used to turn on and off the drop capabilities.
The interface of the usable components are:
type
TDnDRun = class (TCustomDnD)
protected
procedure Loaded; override;
public
procedure Execute;
published
property Active;
property OnDnDStart;
property OnDnDItem;
property OnDnDFinish;
end;
TDnDForm = class(TCustomDnD)
private
FOldDnDefWndProc,
FNewDefWndProc: pointer;
procedure NewDefWndProc (var Msg: TMessage);
protected
procedure Loaded; override;
public
constructor Create (AOwner: TComponent); override;
destructor Destroy; override;
published
property Active;
property OnDnDStart;
property OnDnDItem;
property OnDnDFinish;
end;
TDnDControl = class(TDnDForm)
private
FControl: TWinControl;
procedure SetControl (Value: TWinControl);
protected
procedure Loaded; override;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
published
property Control: TWinControl read FControl write
SetControl;
end;
In each case, the Create and Loaded methods make the necessary API calls so that the control will receive dropped files.
The TDnDRun component is a bit of a cheat in that it only uses ParamCount and ParamStr to return items found on the command line. But it uses the same events interface so I would hope some common code can be used for handling these events.
One final comment is that since the API call to DragAcceptFiles requires a windows handle, then non-windowed visual controls cannot be used to accept dropped files.
The zip file contains the complete source, dcr file and a simple demo. Click here to download it.
Enjoy!