unit DragDropFiles; { Description =========== TDragDropFiles is a component for simple OLE drag-and-drop operations with files. The component is a child-class from TDragDrop. I publish this component simultaneously with TDragDropFilesEx to avoid a brutal code breaking that could discourage some programmers. Probably, I won't enhance the component any longer. Shortcuts does only support the component TDragDropFilesEx! Disclaimer ========== The author disclaims all warranties, expressed or implied, including, without limitation, the warranties of merchantability and of fitness for any purpose. The author assumes no liability for damages, direct or consequential, which may result from the use of this component/unit. Restrictions on Using the Unit / Component ========================================== This unit/component is copyright 1998 by Dieter Steinwedel. ALL RIGHTS ARE RESERVED BY DIETER STEINWEDEL. You are allowed to use it freely subject to the following restrictions: • You are not allowed delete or alter the author's name and copyright in any manner • You are not allowed to publish a copy, modified version or compilation neither for payment in any kind nor freely • You are allowed to create a link to the download in the WWW • These restrictions and terms apply to you as long as until I alter them. Changes can found on my homepage Contact ======= homepage: http://godard.oec.uni-osnabrueck.de/student_home/dsteinwe/delphi/DietersDelphiSite.htm } {$ALIGN ON} {$ASSERTIONS OFF} {$BOOLEVAL OFF} {$DENYPACKAGEUNIT OFF} {$EXTENDEDSYNTAX ON} {$HINTS ON} {$IMPORTEDDATA ON} {$LONGSTRINGS ON} {$OPTIMIZATION ON} {$TYPEDADDRESS OFF} {$TYPEINFO OFF} {$WARNINGS ON} interface uses DragDrop, Windows, Classes, SysUtils, ActiveX; type PDropFiles = ^TDropFiles; TDropFiles = packed record pFiles: DWORD; { offset of file list } pt: TPoint; { drop point (client coords) } fNC: BOOL; { is it on NonClient area } fWide: BOOL; { WIDE character switch } end; TDataObjectFiles = class(TDataObject) private HDropStream:TMemoryStream; public constructor Create(StringList: TStringList); destructor Destroy; override; function RenderData(FormatEtc:TFormatEtc; var StgMedium: TStgMedium): HResult; override; end; TDropTargetFiles = class(TDropTarget) protected procedure AcceptDataObject(DataObj: IDataObject; var Accept:boolean); override; public constructor Create(AOwner: TDragDrop); destructor Destroy; override; procedure RenderDropped(DataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: longint); override; end; TDragDropFiles = class(TDragDrop) private FFileList:TStringList; protected function CreateDataObject:TDataObject; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; property FileList: TStringList read FFileList write FFileList; end; procedure Register; implementation // some local functions -------------------------------------------------------- procedure CopyAsFileList(Strs:TStrings; DataPtr: PChar; DataSize:longint); var s:string; DropFiles: PDropFiles; begin PChar(DropFiles):=DataPtr; inc(DataPtr,DropFiles^.pFiles); while DataPtr^<>#0 do begin if DropFiles^.FWide then begin s:=WideCharToString(PWideChar(DataPtr)); inc(DataPtr,(Length(s)+1)*2); end else begin s:=StrPas(DataPtr); inc(DataPtr, Length(s)+1); end; Strs.Add(s); end; end; // TDataObjectFiles ------------------------------------------------------------- constructor TDataObjectFiles.Create(StringList: TStringList); var FE:TFormatEtc; SM:TStgMedium; i: integer; df:Tdropfiles; pc:array[0..255] of char; begin inherited Create; with FE do begin cfFormat:=cf_HDrop; ptd:=nil; dwAspect:=DVAspect_Content; lindex:=-1; tymed:=tymed_HGlobal; end; SetData(FE,SM,false); HDropStream:=TMemoryStream.Create; with df do begin pfiles:=sizeof(Tdropfiles); pt.x:=0; pt.y:=0; longint(fnc) := 0; longint(Fwide) := 0; end; HDropStream.Write(df,sizeof(df)); for i:=0 to StringList.count-1 do begin strPcopy(pc,StringList[i]+#0); HDropStream.Write(pc,length(StringList[i])+1); end; pc[0]:=#0; HDropStream.Write(pc,1); end; destructor TDataObjectFiles.Destroy; begin HDropStream.free; inherited Destroy; end; function TDataObjectFiles.RenderData(FormatEtc:TFormatEtc; var StgMedium: TStgMedium):HResult; var h: HGlobal; p:pointer; begin Result:=E_Fail; if FormatEtc.cfFormat=cf_HDrop then begin h:=GlobalAlloc(GHND or GMEM_SHARE, HDropStream.Size); if h=0 then begin Result:=E_OUTOFMEMORY; exit; end; p:=globallock(h); HDropStream.Seek(0,0); HDropStream.Read(p^,HDropStream.Size); globalunlock(h); with StgMedium do begin tymed:=TYMED_HGLOBAL; hGlobal := h; unkForRelease := nil; end; Result:=S_OK; end; end; // TDropTargetFiles ------------------------------------------------------------- constructor TDropTargetFiles.Create(AOwner: TDragDrop); begin inherited Create(AOwner); end; destructor TDropTargetFiles.Destroy; begin inherited Destroy; end; procedure TDropTargetFiles.AcceptDataObject(DataObj: IDataObject; var Accept:boolean); var FE:TFormatEtc; begin with FE do begin cfFormat:=cf_HDrop; ptd:=nil; dwAspect:=DVASPECT_CONTENT; lindex:=-1; tymed:=TYMED_HGLOBAL; end; Accept:=DataObj.QueryGetData(FE)=S_OK; end; procedure TDropTargetFiles.RenderDropped(DataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: longint); var FE: TFormatEtc; SM: TStgMedium; DataSize: longint; DataPtr: pointer; begin with FE do begin cfFormat:=CF_HDROP; ptd:=nil; dwAspect:=DVASPECT_CONTENT; lindex:=-1; tymed:=TYMED_HGLOBAL; end; if DataObj.GetData(FE,SM)=S_Ok then begin DataSize:=GlobalSize(SM.HGlobal); try DataPtr:=GlobalLock(SM.HGlobal); TDragDropFiles(FOwner).FFileList.Clear; CopyAsFileList(TDragDropFiles(FOwner).FFileList, DataPtr, DataSize); finally GlobalUnLock(SM.HGlobal); ReleaseStgMedium(SM); end; end; end; // TDragDropFiles --------------------------------------------------------------- constructor TDragDropFiles.Create(AOwner: TComponent); begin inherited Create(AOwner); FFileList:=TStringList.Create; FFileList.sorted:=false; FFileList.Duplicates:=dupIgnore; FDropTarget._Release; FDropTarget:=TDropTargetFiles.Create(self); SourceCompatibility:=[]; end; destructor TDragDropFiles.Destroy; begin FFileList.Free; inherited destroy; end; function TDragDropFiles.CreateDataObject:TDataObject; begin if FFileList.Count>0 then Result:=TDataObjectFiles.Create(FFileList) else Result:=nil; end; // Register Component ---------------------------------------------------------- procedure Register; begin {MP}RegisterComponents({'Shell32'}'DragDrop', [TDragDropFiles]); end; end.