DragDropFiles.pas 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. unit DragDropFiles;
  2. {
  3. Description
  4. ===========
  5. TDragDropFiles is a component for simple OLE drag-and-drop operations
  6. with files. The component is a child-class from TDragDrop.
  7. I publish this component simultaneously with TDragDropFilesEx to avoid
  8. a brutal code breaking that could discourage some programmers. Probably,
  9. I won't enhance the component any longer.
  10. Shortcuts does only support the component TDragDropFilesEx!
  11. Disclaimer
  12. ==========
  13. The author disclaims all warranties, expressed or implied, including,
  14. without limitation, the warranties of merchantability and of fitness
  15. for any purpose. The author assumes no liability for damages, direct or
  16. consequential, which may result from the use of this component/unit.
  17. Restrictions on Using the Unit / Component
  18. ==========================================
  19. This unit/component is copyright 1998 by Dieter Steinwedel. ALL RIGHTS
  20. ARE RESERVED BY DIETER STEINWEDEL. You are allowed to use it freely
  21. subject to the following restrictions:
  22. • You are not allowed delete or alter the author's name and
  23. copyright in any manner
  24. • You are not allowed to publish a copy, modified version or
  25. compilation neither for payment in any kind nor freely
  26. • You are allowed to create a link to the download in the WWW
  27. • These restrictions and terms apply to you as long as until
  28. I alter them. Changes can found on my homepage
  29. Contact
  30. =======
  31. homepage: http://godard.oec.uni-osnabrueck.de/student_home/dsteinwe/delphi/DietersDelphiSite.htm
  32. }
  33. {$ALIGN ON}
  34. {$ASSERTIONS OFF}
  35. {$BOOLEVAL OFF}
  36. {$DENYPACKAGEUNIT OFF}
  37. {$EXTENDEDSYNTAX ON}
  38. {$HINTS ON}
  39. {$IMPORTEDDATA ON}
  40. {$LONGSTRINGS ON}
  41. {$OPTIMIZATION ON}
  42. {$TYPEDADDRESS OFF}
  43. {$TYPEINFO OFF}
  44. {$WARNINGS ON}
  45. interface
  46. uses DragDrop, Windows, Classes, SysUtils, ActiveX;
  47. type
  48. PDropFiles = ^TDropFiles;
  49. TDropFiles = packed record
  50. pFiles: DWORD; { offset of file list }
  51. pt: TPoint; { drop point (client coords) }
  52. fNC: BOOL; { is it on NonClient area }
  53. fWide: BOOL; { WIDE character switch }
  54. end;
  55. TDataObjectFiles = class(TDataObject)
  56. private
  57. HDropStream:TMemoryStream;
  58. public
  59. constructor Create(StringList: TStringList);
  60. destructor Destroy; override;
  61. function RenderData(FormatEtc:TFormatEtc;
  62. var StgMedium: TStgMedium): HResult; override;
  63. end;
  64. TDropTargetFiles = class(TDropTarget)
  65. protected
  66. procedure AcceptDataObject(DataObj: IDataObject; var Accept:boolean); override;
  67. public
  68. constructor Create(AOwner: TDragDrop);
  69. destructor Destroy; override;
  70. procedure RenderDropped(DataObj: IDataObject; grfKeyState: Longint;
  71. pt: TPoint; var dwEffect: longint); override;
  72. end;
  73. TDragDropFiles = class(TDragDrop)
  74. private
  75. FFileList:TStringList;
  76. protected
  77. function CreateDataObject:TDataObject; override;
  78. public
  79. constructor Create(AOwner: TComponent); override;
  80. destructor Destroy; override;
  81. property FileList: TStringList read FFileList write FFileList;
  82. end;
  83. procedure Register;
  84. implementation
  85. // some local functions --------------------------------------------------------
  86. procedure CopyAsFileList(Strs:TStrings; DataPtr: PChar; DataSize:longint);
  87. var s:string;
  88. DropFiles: PDropFiles;
  89. begin
  90. PChar(DropFiles):=DataPtr;
  91. inc(DataPtr,DropFiles^.pFiles);
  92. while DataPtr^<>#0 do
  93. begin
  94. if DropFiles^.FWide then
  95. begin
  96. s:=WideCharToString(PWideChar(DataPtr));
  97. inc(DataPtr,(Length(s)+1)*2);
  98. end
  99. else
  100. begin
  101. s:=StrPas(DataPtr);
  102. inc(DataPtr, Length(s)+1);
  103. end;
  104. Strs.Add(s);
  105. end;
  106. end;
  107. // TDataObjectFiles -------------------------------------------------------------
  108. constructor TDataObjectFiles.Create(StringList: TStringList);
  109. var FE:TFormatEtc;
  110. SM:TStgMedium;
  111. i: integer;
  112. df:Tdropfiles;
  113. pc:array[0..255] of char;
  114. begin
  115. inherited Create;
  116. with FE do
  117. begin
  118. cfFormat:=cf_HDrop;
  119. ptd:=nil;
  120. dwAspect:=DVAspect_Content;
  121. lindex:=-1;
  122. tymed:=tymed_HGlobal;
  123. end;
  124. SetData(FE,SM,false);
  125. HDropStream:=TMemoryStream.Create;
  126. with df do
  127. begin
  128. pfiles:=sizeof(Tdropfiles);
  129. pt.x:=0;
  130. pt.y:=0;
  131. longint(fnc) := 0;
  132. longint(Fwide) := 0;
  133. end;
  134. HDropStream.Write(df,sizeof(df));
  135. for i:=0 to StringList.count-1 do
  136. begin
  137. strPcopy(pc,StringList[i]+#0);
  138. HDropStream.Write(pc,length(StringList[i])+1);
  139. end;
  140. pc[0]:=#0;
  141. HDropStream.Write(pc,1);
  142. end;
  143. destructor TDataObjectFiles.Destroy;
  144. begin
  145. HDropStream.free;
  146. inherited Destroy;
  147. end;
  148. function TDataObjectFiles.RenderData(FormatEtc:TFormatEtc;
  149. var StgMedium: TStgMedium):HResult;
  150. var h: HGlobal;
  151. p:pointer;
  152. begin
  153. Result:=E_Fail;
  154. if FormatEtc.cfFormat=cf_HDrop then
  155. begin
  156. h:=GlobalAlloc(GHND or GMEM_SHARE, HDropStream.Size);
  157. if h=0 then
  158. begin
  159. Result:=E_OUTOFMEMORY;
  160. exit;
  161. end;
  162. p:=globallock(h);
  163. HDropStream.Seek(0,0);
  164. HDropStream.Read(p^,HDropStream.Size);
  165. globalunlock(h);
  166. with StgMedium do
  167. begin
  168. tymed:=TYMED_HGLOBAL;
  169. hGlobal := h;
  170. unkForRelease := nil;
  171. end;
  172. Result:=S_OK;
  173. end;
  174. end;
  175. // TDropTargetFiles -------------------------------------------------------------
  176. constructor TDropTargetFiles.Create(AOwner: TDragDrop);
  177. begin
  178. inherited Create(AOwner);
  179. end;
  180. destructor TDropTargetFiles.Destroy;
  181. begin
  182. inherited Destroy;
  183. end;
  184. procedure TDropTargetFiles.AcceptDataObject(DataObj: IDataObject;
  185. var Accept:boolean);
  186. var FE:TFormatEtc;
  187. begin
  188. with FE do
  189. begin
  190. cfFormat:=cf_HDrop;
  191. ptd:=nil;
  192. dwAspect:=DVASPECT_CONTENT;
  193. lindex:=-1;
  194. tymed:=TYMED_HGLOBAL;
  195. end;
  196. Accept:=DataObj.QueryGetData(FE)=S_OK;
  197. end;
  198. procedure TDropTargetFiles.RenderDropped(DataObj: IDataObject; grfKeyState: Longint;
  199. pt: TPoint; var dwEffect: longint);
  200. var FE: TFormatEtc;
  201. SM: TStgMedium;
  202. DataSize: longint;
  203. DataPtr: pointer;
  204. begin
  205. with FE do
  206. begin
  207. cfFormat:=CF_HDROP;
  208. ptd:=nil;
  209. dwAspect:=DVASPECT_CONTENT;
  210. lindex:=-1;
  211. tymed:=TYMED_HGLOBAL;
  212. end;
  213. if DataObj.GetData(FE,SM)=S_Ok then
  214. begin
  215. DataSize:=GlobalSize(SM.HGlobal);
  216. try
  217. DataPtr:=GlobalLock(SM.HGlobal);
  218. TDragDropFiles(FOwner).FFileList.Clear;
  219. CopyAsFileList(TDragDropFiles(FOwner).FFileList, DataPtr,
  220. DataSize);
  221. finally
  222. GlobalUnLock(SM.HGlobal);
  223. ReleaseStgMedium(SM);
  224. end;
  225. end;
  226. end;
  227. // TDragDropFiles ---------------------------------------------------------------
  228. constructor TDragDropFiles.Create(AOwner: TComponent);
  229. begin
  230. inherited Create(AOwner);
  231. FFileList:=TStringList.Create;
  232. FFileList.sorted:=false;
  233. FFileList.Duplicates:=dupIgnore;
  234. FDropTarget._Release;
  235. FDropTarget:=TDropTargetFiles.Create(self);
  236. SourceCompatibility:=[];
  237. end;
  238. destructor TDragDropFiles.Destroy;
  239. begin
  240. FFileList.Free;
  241. inherited destroy;
  242. end;
  243. function TDragDropFiles.CreateDataObject:TDataObject;
  244. begin
  245. if FFileList.Count>0 then Result:=TDataObjectFiles.Create(FFileList)
  246. else Result:=nil;
  247. end;
  248. // Register Component ----------------------------------------------------------
  249. procedure Register;
  250. begin
  251. {MP}RegisterComponents({'Shell32'}'DragDrop', [TDragDropFiles]);
  252. end;
  253. end.