unit DropFileClass;
interface
uses
Windows, Messages, Classes, SysUtils, AppEvnts,
Controls, ShellAPI, FileCtrl, ActiveX, ComObj, ShlObj;
type
TDropEffect = (deNone, deCopy, deMove, deLink);
TDropFile = class(TApplicationEvents, IDropSource)
protected
procedure ApplicationEventsMessage(var Msg: tagMSG; var Handled: Boolean); virtual;
function QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: Longint): HResult; stdcall;
function GiveFeedback(dwEffect: Longint): HResult; stdcall;
public
DropEffect: TDropEffect;
Files: TStringList;
OnDropFiles : TNotifyEvent;
function DropOut(Directory: String; AFileName: String): Integer; overload;
function DropOut(Directory: String; AFileList: TStrings): Integer; overload;
function DropOut(AFileList: TStrings): Integer; overload;
function DropOut(AFileName: String): Integer; overload;
function MouseMoveDrop(Sender: TObject; Shift: TShiftState; X, Y: Integer; offset: integer = 0):boolean;
constructor Create(AOwner: TWinControl);
destructor Destroy; override;
end;
implementation
procedure TDropFile.ApplicationEventsMessage(var Msg: tagMSG; var Handled: Boolean);
var nCount, nFile : UINT;
sFileNm : string;
dwChars : DWORD;
const QUERY_FILES_COUNT = UINT($FFFFFFFF);
begin
if (Msg.message=WM_DROPFILES) and (Msg.hwnd = TWinControl(self.Owner).Handle) then begin
if @self.OnDropFiles=nil then begin
Handled:=true;
exit;
end;
Handled:=true;
nCount := DragQueryFile( Msg.wParam, QUERY_FILES_COUNT, nil, 0);
if nCount = 0 then Exit;
Files.Clear;
try
for nFile := 0 to nCount-1 do begin
dwChars := DragQueryFile( Msg.wParam, nFile, nil,0);
Inc( dwChars);
SetLength( sFileNm, dwChars);
dwChars := DragQueryFile( Msg.wParam, nFile, PChar(sFileNm), dwChars);
if dwChars > 0 then begin
SetLength( sFileNm, dwChars);
Files.Add(sFileNm);
end;
end;
finally
if @self.OnDropFiles<>nil then OnDropFiles(self);
end;
end;
end;
constructor TDropFile.Create(AOwner: TWinControl);
begin
TApplicationEvents(self).Create(AOwner);
self.OnMessage:=self.ApplicationEventsMessage;
Files:=TStringList.Create;
DropEffect:=deCopy;
DragAcceptFiles(TWinControl(Owner).Handle, TRUE);
end;
destructor TDropFile.Destroy;
begin
Files.free;
if Assigned(Owner) then DragAcceptFiles(TWinControl(Owner).Handle, FALSE);
inherited;
end;
function TDropFile.DropOut(AFileList: TStrings): Integer;
var s1:string; i:integer;
begin
if AFileList.Count=0 then exit;
Files.Clear;
s1:=ExtractFilePath(AFileList[0]);
i:=0;
repeat
if (s1<>ExtractFilePath(AFileList[i])) then break;
Files.Add(ExtractFileName(AFileList[i]));
inc(i);
until (i=AFileList.Count);
DropOut(s1,Files);
Files.Clear;
end;
function TDropFile.DropOut(Directory: String; AFileList: TStrings): Integer;
var
dataObj: IDataObject;
Root: IShellFolder;
pchEaten: ULONG;
DirectoryItemIDList: PItemIDList;
dwAttributes: ULONG;
Folder: IShellFolder;
i: Integer;
ItemIDLists: array of PItemIDList;
dwOKEffects: Longint;
begin
OleCheck(SHGetDesktopFolder(Root));
OleCheck(Root.ParseDisplayName(0, nil, PWideChar(WideString(Directory)),
pchEaten, DirectoryItemIDList, dwAttributes));
try
OleCheck(Root.BindToObject(DirectoryItemIDList, nil, IShellFolder, Folder));
SetLength(ItemIDLists, AFileList.Count);
for i:=0 to AFileList.Count-1 do OleCheck(Folder.ParseDisplayName(0, nil,
PWideChar(WideString(AFileList[i])),
pchEaten, ItemIDLists[i], dwAttributes));
try
OleCheck(Folder.GetUIObjectOf(0, AFileList.Count, ItemIDLists[0],
IDataObject, nil, dataObj));
finally
for i:=0 to AFileList.Count-1 do CoTaskMemFree(ItemIDLists[i]);
end;
dwOKEffects:=0;
if deNone = DropEffect then dwOKEffects:=dwOKEffects or DROPEFFECT_NONE;
if deCopy = DropEffect then dwOKEffects:=dwOKEffects or DROPEFFECT_COPY;
if deMove = DropEffect then dwOKEffects:=dwOKEffects or DROPEFFECT_MOVE;
if deLink = DropEffect then dwOKEffects:=dwOKEffects or DROPEFFECT_LINK;
DoDragDrop(dataObj, Self, dwOKEffects, Result);
finally
CoTaskMemFree(DirectoryItemIDList);
end;
end;
function TDropFile.DropOut(Directory, AFileName: String): Integer;
begin
Files.Clear;
try
Files.Add(AFileName);
Result:=DropOut(Directory, Files);
finally
Files.Clear;
end;
end;
function TDropFile.DropOut(AFileName: String): Integer;
begin
Files.Clear;
try
Files.Add(ExtractFileName(AFileName));
Result:=DropOut(ExtractFilePath(AFileName), Files);
finally
Files.Clear;
end;
end;
function TDropFile.GiveFeedback(dwEffect: Integer): HResult;
begin
Result:=DRAGDROP_S_USEDEFAULTCURSORS;
end;
function TDropFile.MouseMoveDrop(Sender: TObject; Shift: TShiftState; X, Y, offset: Integer): boolean;
begin
result:=false;
if not (Sender is TControl) then exit;
if (ssLeft in Shift) and
((x<=offset)or(x>=TControl(Sender).Width-5-offset) or
(y<=offset)or(y>=TControl(Sender).Height-5-offset)) then result:=true;
end;
function TDropFile.QueryContinueDrag(fEscapePressed: BOOL;
grfKeyState: Integer): HResult;
begin
if fEscapePressed then Result:=DRAGDROP_S_CANCEL
else if (grfKeyState and MK_LBUTTON)=0 then Result:=DRAGDROP_S_DROP
else Result:=S_OK;
end;
initialization
OleInitialize(nil);
finalization
OleUninitialize;
end.