DragDropFormats.pas 81 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823
  1. unit DragDropFormats;
  2. // -----------------------------------------------------------------------------
  3. // Project: Drag and Drop Component Suite.
  4. // Module: DragDropFormats
  5. // Description: Implements commonly used clipboard formats and base classes.
  6. // Version: 4.0
  7. // Date: 18-MAY-2001
  8. // Target: Win32, Delphi 5-6
  9. // Authors: Anders Melander, anders@melander.dk, http://www.melander.dk
  10. // Copyright © 1997-2001 Angus Johnson & Anders Melander
  11. // -----------------------------------------------------------------------------
  12. interface
  13. uses
  14. DragDrop,
  15. Windows,
  16. Classes,
  17. ActiveX,
  18. ShlObj;
  19. {$include DragDrop.inc}
  20. type
  21. ////////////////////////////////////////////////////////////////////////////////
  22. //
  23. // TStreamList
  24. //
  25. ////////////////////////////////////////////////////////////////////////////////
  26. // Utility class used by TFileContentsStreamClipboardFormat and
  27. // TDataStreamDataFormat.
  28. ////////////////////////////////////////////////////////////////////////////////
  29. TStreamList = class(TObject)
  30. private
  31. FStreams : TStrings;
  32. FOnChanging : TNotifyEvent;
  33. protected
  34. function GetStream(Index: integer): TStream;
  35. function GetCount: integer;
  36. procedure Changing;
  37. public
  38. constructor Create;
  39. destructor Destroy; override;
  40. function Add(Stream: TStream): integer;
  41. function AddNamed(Stream: TStream; Name: string): integer;
  42. procedure Delete(Index: integer);
  43. procedure Clear;
  44. procedure Assign(Value: TStreamList);
  45. property Count: integer read GetCount;
  46. property Streams[Index: integer]: TStream read GetStream; default;
  47. property Names: TStrings read FStreams;
  48. property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
  49. end;
  50. ////////////////////////////////////////////////////////////////////////////////
  51. //
  52. // TInterfaceList
  53. //
  54. ////////////////////////////////////////////////////////////////////////////////
  55. // List of named interfaces.
  56. // Note: Delphi 5 also implements a TInterfaceList, but it can not be used
  57. // because it doesn't support change notification and isn't extensible.
  58. ////////////////////////////////////////////////////////////////////////////////
  59. // Utility class used by TFileContentsStorageClipboardFormat.
  60. ////////////////////////////////////////////////////////////////////////////////
  61. TInterfaceList = class(TObject)
  62. private
  63. FList : TStrings;
  64. FOnChanging : TNotifyEvent;
  65. protected
  66. function GetCount: integer;
  67. function GetName(Index: integer): string;
  68. function GetItem(Index: integer): IUnknown;
  69. procedure Changing;
  70. public
  71. constructor Create;
  72. destructor Destroy; override;
  73. function Add(Item: IUnknown): integer;
  74. function AddNamed(Item: IUnknown; Name: string): integer;
  75. procedure Delete(Index: integer);
  76. procedure Clear;
  77. procedure Assign(Value: TInterfaceList);
  78. property Items[Index: integer]: IUnknown read GetItem; default;
  79. property Names[Index: integer]: string read GetName;
  80. property Count: integer read GetCount;
  81. property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
  82. end;
  83. ////////////////////////////////////////////////////////////////////////////////
  84. //
  85. // TStorageInterfaceList
  86. //
  87. ////////////////////////////////////////////////////////////////////////////////
  88. // List of IStorage interfaces.
  89. // Used by TFileContentsStorageClipboardFormat.
  90. ////////////////////////////////////////////////////////////////////////////////
  91. TStorageInterfaceList = class(TInterfaceList)
  92. private
  93. protected
  94. function GetStorage(Index: integer): IStorage;
  95. public
  96. property Storages[Index: integer]: IStorage read GetStorage; default;
  97. end;
  98. ////////////////////////////////////////////////////////////////////////////////
  99. //
  100. // TFixedStreamAdapter
  101. //
  102. ////////////////////////////////////////////////////////////////////////////////
  103. // TFixedStreamAdapter fixes several serious bugs in TStreamAdapter.CopyTo.
  104. ////////////////////////////////////////////////////////////////////////////////
  105. TFixedStreamAdapter = class(TStreamAdapter, IStream)
  106. public
  107. function CopyTo(stm: IStream; cb: Largeint; out cbRead: Largeint;
  108. out cbWritten: Largeint): HResult; override; stdcall;
  109. end;
  110. ////////////////////////////////////////////////////////////////////////////////
  111. //
  112. // TMemoryList
  113. //
  114. ////////////////////////////////////////////////////////////////////////////////
  115. // List which owns the memory blocks it points to.
  116. ////////////////////////////////////////////////////////////////////////////////
  117. TMemoryList = class(TObject)
  118. private
  119. FList: TList;
  120. protected
  121. function Get(Index: Integer): Pointer;
  122. function GetCount: Integer;
  123. public
  124. constructor Create;
  125. destructor Destroy; override;
  126. function Add(Item: Pointer): Integer;
  127. procedure Clear;
  128. procedure Delete(Index: Integer);
  129. property Count: Integer read GetCount;
  130. property Items[Index: Integer]: Pointer read Get; default;
  131. end;
  132. ////////////////////////////////////////////////////////////////////////////////
  133. //
  134. // TCustomSimpleClipboardFormat
  135. //
  136. ////////////////////////////////////////////////////////////////////////////////
  137. // Abstract base class for simple clipboard formats stored in global memory
  138. // or a stream.
  139. ////////////////////////////////////////////////////////////////////////////////
  140. //
  141. // Two different methods of data transfer from the medium to the object are
  142. // supported:
  143. //
  144. // 1) Descendant class reads data from a buffer provided by the base class.
  145. //
  146. // 2) Base class reads data from a buffer provided by the descendant class.
  147. //
  148. // Method #1 only requires that the descedant class implements the ReadData.
  149. //
  150. // Method #2 requires that the descedant class overrides the default
  151. // DoGetDataSized method. The descedant DoGetDataSized method should allocate a
  152. // buffer of the specified size and then call the ReadDataInto method to
  153. // transfer data to the buffer. Even though the ReadData method will not be used
  154. // in this scenario, it should be implemented as an empty method (to avoid
  155. // abstract warnings).
  156. //
  157. // The WriteData method must be implemented regardless of which of the two
  158. // approaches the class implements.
  159. //
  160. ////////////////////////////////////////////////////////////////////////////////
  161. TCustomSimpleClipboardFormat = class(TClipboardFormat)
  162. private
  163. protected
  164. function DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean; override;
  165. //: Transfer data from medium to a buffer of the specified size.
  166. function DoGetDataSized(ADataObject: IDataObject; const AMedium: TStgMedium;
  167. Size: integer): boolean; virtual;
  168. //: Transfer data from the specified buffer to the objects storage.
  169. function ReadData(Value: pointer; Size: integer): boolean; virtual; abstract;
  170. //: Transfer data from the medium to the specified buffer.
  171. function ReadDataInto(ADataObject: IDataObject; const AMedium: TStgMedium;
  172. Buffer: pointer; Size: integer): boolean; virtual;
  173. function DoSetData(const FormatEtcIn: TFormatEtc;
  174. var AMedium: TStgMedium): boolean; override;
  175. //: Transfer data from the objects storage to the specified buffer.
  176. function WriteData(Value: pointer; Size: integer): boolean; virtual; abstract;
  177. function GetSize: integer; virtual; abstract;
  178. public
  179. constructor Create; override;
  180. end;
  181. ////////////////////////////////////////////////////////////////////////////////
  182. //
  183. // TCustomStringClipboardFormat
  184. //
  185. ////////////////////////////////////////////////////////////////////////////////
  186. // Abstract base class for simple clipboard formats.
  187. // The data is stored in a string.
  188. ////////////////////////////////////////////////////////////////////////////////
  189. TCustomStringClipboardFormat = class(TCustomSimpleClipboardFormat)
  190. private
  191. FData: string;
  192. FTrimZeroes: boolean;
  193. protected
  194. function ReadData(Value: pointer; Size: integer): boolean; override;
  195. function WriteData(Value: pointer; Size: integer): boolean; override;
  196. function GetSize: integer; override;
  197. function GetString: string;
  198. procedure SetString(const Value: string);
  199. property Data: string read FData write FData; // DONE : Why is SetString used instead of FData?
  200. public
  201. procedure Clear; override;
  202. function HasData: boolean; override;
  203. property TrimZeroes: boolean read FTrimZeroes write FTrimZeroes;
  204. end;
  205. ////////////////////////////////////////////////////////////////////////////////
  206. //
  207. // TCustomStringListClipboardFormat
  208. //
  209. ////////////////////////////////////////////////////////////////////////////////
  210. // Abstract base class for simple cr/lf delimited string clipboard formats.
  211. // The data is stored in a TStringList.
  212. ////////////////////////////////////////////////////////////////////////////////
  213. TCustomStringListClipboardFormat = class(TCustomSimpleClipboardFormat)
  214. private
  215. FLines : TStrings;
  216. protected
  217. function ReadData(Value: pointer; Size: integer): boolean; override;
  218. function WriteData(Value: pointer; Size: integer): boolean; override;
  219. function GetSize: integer; override;
  220. function GetLines: TStrings;
  221. property Lines: TStrings read FLines;
  222. public
  223. constructor Create; override;
  224. destructor Destroy; override;
  225. procedure Clear; override;
  226. function HasData: boolean; override;
  227. end;
  228. ////////////////////////////////////////////////////////////////////////////////
  229. //
  230. // TCustomTextClipboardFormat
  231. //
  232. ////////////////////////////////////////////////////////////////////////////////
  233. // Abstract base class for simple text based clipboard formats.
  234. ////////////////////////////////////////////////////////////////////////////////
  235. TCustomTextClipboardFormat = class(TCustomStringClipboardFormat)
  236. private
  237. protected
  238. function GetSize: integer; override;
  239. property Text: string read GetString write SetString;
  240. public
  241. constructor Create; override;
  242. end;
  243. ////////////////////////////////////////////////////////////////////////////////
  244. //
  245. // TCustomWideTextClipboardFormat
  246. //
  247. ////////////////////////////////////////////////////////////////////////////////
  248. // Abstract base class for simple wide string clipboard formats storing the data
  249. // in a wide string.
  250. ////////////////////////////////////////////////////////////////////////////////
  251. TCustomWideTextClipboardFormat = class(TCustomSimpleClipboardFormat)
  252. private
  253. FText : WideString;
  254. protected
  255. function ReadData(Value: pointer; Size: integer): boolean; override;
  256. function WriteData(Value: pointer; Size: integer): boolean; override;
  257. function GetSize: integer; override;
  258. function GetText: WideString;
  259. procedure SetText(const Value: WideString);
  260. property Text: WideString read FText write FText;
  261. public
  262. procedure Clear; override;
  263. function HasData: boolean; override;
  264. end;
  265. ////////////////////////////////////////////////////////////////////////////////
  266. //
  267. // TTextClipboardFormat
  268. //
  269. ////////////////////////////////////////////////////////////////////////////////
  270. TTextClipboardFormat = class(TCustomTextClipboardFormat)
  271. public
  272. function GetClipboardFormat: TClipFormat; override;
  273. property Text;
  274. end;
  275. ////////////////////////////////////////////////////////////////////////////////
  276. //
  277. // TCustomDWORDClipboardFormat
  278. //
  279. ////////////////////////////////////////////////////////////////////////////////
  280. TCustomDWORDClipboardFormat = class(TCustomSimpleClipboardFormat)
  281. private
  282. FValue : DWORD;
  283. protected
  284. function ReadData(Value: pointer; Size: integer): boolean; override;
  285. function WriteData(Value: pointer; Size: integer): boolean; override;
  286. function GetSize: integer; override;
  287. function GetValueDWORD: DWORD;
  288. procedure SetValueDWORD(Value: DWORD);
  289. function GetValueInteger: integer;
  290. procedure SetValueInteger(Value: integer);
  291. function GetValueLongInt: longInt;
  292. procedure SetValueLongInt(Value: longInt);
  293. function GetValueBoolean: boolean;
  294. procedure SetValueBoolean(Value: boolean);
  295. public
  296. procedure Clear; override;
  297. end;
  298. ////////////////////////////////////////////////////////////////////////////////
  299. //
  300. // TFileGroupDescritorClipboardFormat
  301. //
  302. ////////////////////////////////////////////////////////////////////////////////
  303. TFileGroupDescritorClipboardFormat = class(TCustomSimpleClipboardFormat)
  304. private
  305. FFileGroupDescriptor : PFileGroupDescriptor;
  306. protected
  307. function ReadData(Value: pointer; Size: integer): boolean; override;
  308. function WriteData(Value: pointer; Size: integer): boolean; override;
  309. function GetSize: integer; override;
  310. public
  311. function GetClipboardFormat: TClipFormat; override;
  312. destructor Destroy; override;
  313. procedure Clear; override;
  314. function HasData: boolean; override;
  315. property FileGroupDescriptor: PFileGroupDescriptor read FFileGroupDescriptor;
  316. procedure CopyFrom(AFileGroupDescriptor: PFileGroupDescriptor);
  317. end;
  318. ////////////////////////////////////////////////////////////////////////////////
  319. //
  320. // TFileGroupDescritorWClipboardFormat
  321. //
  322. ////////////////////////////////////////////////////////////////////////////////
  323. // Warning: TFileGroupDescriptorW has wrong declaration in ShlObj.pas!
  324. TFileGroupDescriptorW = record
  325. cItems: UINT;
  326. fgd: array[0..0] of TFileDescriptorW;
  327. end;
  328. PFileGroupDescriptorW = ^TFileGroupDescriptorW;
  329. TFileGroupDescritorWClipboardFormat = class(TCustomSimpleClipboardFormat)
  330. private
  331. FFileGroupDescriptor : PFileGroupDescriptorW;
  332. protected
  333. function ReadData(Value: pointer; Size: integer): boolean; override;
  334. function WriteData(Value: pointer; Size: integer): boolean; override;
  335. function GetSize: integer; override;
  336. public
  337. function GetClipboardFormat: TClipFormat; override;
  338. destructor Destroy; override;
  339. procedure Clear; override;
  340. function HasData: boolean; override;
  341. property FileGroupDescriptor: PFileGroupDescriptorW read FFileGroupDescriptor;
  342. procedure CopyFrom(AFileGroupDescriptor: PFileGroupDescriptorW);
  343. end;
  344. ////////////////////////////////////////////////////////////////////////////////
  345. //
  346. // TFileContentsClipboardFormat
  347. //
  348. ////////////////////////////////////////////////////////////////////////////////
  349. // Note: File contents must be zero terminated, so we descend from
  350. // TCustomTextClipboardFormat instead of TCustomStringClipboardFormat.
  351. ////////////////////////////////////////////////////////////////////////////////
  352. TFileContentsClipboardFormat = class(TCustomTextClipboardFormat)
  353. public
  354. function GetClipboardFormat: TClipFormat; override;
  355. constructor Create; override;
  356. property Data;
  357. end;
  358. ////////////////////////////////////////////////////////////////////////////////
  359. //
  360. // TFileContentsStreamClipboardFormat
  361. //
  362. ////////////////////////////////////////////////////////////////////////////////
  363. TFileContentsStreamClipboardFormat = class(TClipboardFormat)
  364. private
  365. FStreams: TStreamList;
  366. protected
  367. public
  368. constructor Create; override;
  369. destructor Destroy; override;
  370. function GetClipboardFormat: TClipFormat; override;
  371. function GetData(DataObject: IDataObject): boolean; override;
  372. procedure Clear; override;
  373. function HasData: boolean; override;
  374. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  375. property Streams: TStreamList read FStreams;
  376. end;
  377. ////////////////////////////////////////////////////////////////////////////////
  378. //
  379. // TFileContentsStreamOnDemandClipboardFormat
  380. //
  381. ////////////////////////////////////////////////////////////////////////////////
  382. // Yeah, it's a long name, but I like my names descriptive.
  383. ////////////////////////////////////////////////////////////////////////////////
  384. TVirtualFileStreamDataFormat = class;
  385. TFileContentsStreamOnDemandClipboardFormat = class;
  386. TOnGetStreamEvent = procedure(Sender: TFileContentsStreamOnDemandClipboardFormat;
  387. Index: integer; out AStream: IStream) of object;
  388. TFileContentsStreamOnDemandClipboardFormat = class(TClipboardFormat)
  389. private
  390. FOnGetStream: TOnGetStreamEvent;
  391. FGotData: boolean;
  392. FDataRequested: boolean;
  393. protected
  394. function DoSetData(const FormatEtcIn: TFormatEtc;
  395. var AMedium: TStgMedium): boolean; override;
  396. public
  397. constructor Create; override;
  398. destructor Destroy; override;
  399. function GetClipboardFormat: TClipFormat; override;
  400. function GetData(DataObject: IDataObject): boolean; override;
  401. procedure Clear; override;
  402. function HasData: boolean; override;
  403. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  404. function Assign(Source: TCustomDataFormat): boolean; override;
  405. function GetStream(Index: integer): IStream;
  406. property OnGetStream: TOnGetStreamEvent read FOnGetStream write FOnGetStream;
  407. end;
  408. ////////////////////////////////////////////////////////////////////////////////
  409. //
  410. // TFileContentsStorageClipboardFormat
  411. //
  412. ////////////////////////////////////////////////////////////////////////////////
  413. TFileContentsStorageClipboardFormat = class(TClipboardFormat)
  414. private
  415. FStorages : TStorageInterfaceList;
  416. protected
  417. public
  418. constructor Create; override;
  419. destructor Destroy; override;
  420. function GetClipboardFormat: TClipFormat; override;
  421. function GetData(DataObject: IDataObject): boolean; override;
  422. procedure Clear; override;
  423. function HasData: boolean; override;
  424. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  425. property Storages: TStorageInterfaceList read FStorages;
  426. end;
  427. ////////////////////////////////////////////////////////////////////////////////
  428. //
  429. // TPreferredDropEffectClipboardFormat
  430. //
  431. ////////////////////////////////////////////////////////////////////////////////
  432. TPreferredDropEffectClipboardFormat = class(TCustomDWORDClipboardFormat)
  433. public
  434. class function GetClassClipboardFormat: TClipFormat;
  435. function GetClipboardFormat: TClipFormat; override;
  436. function HasData: boolean; override;
  437. property Value: longInt read GetValueLongInt write SetValueLongInt;
  438. end;
  439. ////////////////////////////////////////////////////////////////////////////////
  440. //
  441. // TPerformedDropEffectClipboardFormat
  442. //
  443. ////////////////////////////////////////////////////////////////////////////////
  444. TPerformedDropEffectClipboardFormat = class(TCustomDWORDClipboardFormat)
  445. public
  446. function GetClipboardFormat: TClipFormat; override;
  447. property Value: longInt read GetValueLongInt write SetValueLongInt;
  448. end;
  449. ////////////////////////////////////////////////////////////////////////////////
  450. //
  451. // TLogicalPerformedDropEffectClipboardFormat
  452. //
  453. ////////////////////////////////////////////////////////////////////////////////
  454. // Microsoft's latest (so far) "logical" solution to the never ending attempts
  455. // of reporting back to the source which operation actually took place. Sigh!
  456. ////////////////////////////////////////////////////////////////////////////////
  457. TLogicalPerformedDropEffectClipboardFormat = class(TCustomDWORDClipboardFormat)
  458. public
  459. function GetClipboardFormat: TClipFormat; override;
  460. property Value: longInt read GetValueLongInt write SetValueLongInt;
  461. end;
  462. ////////////////////////////////////////////////////////////////////////////////
  463. //
  464. // TPasteSuccededClipboardFormat
  465. //
  466. ////////////////////////////////////////////////////////////////////////////////
  467. TPasteSuccededClipboardFormat = class(TCustomDWORDClipboardFormat)
  468. public
  469. function GetClipboardFormat: TClipFormat; override;
  470. property Value: longInt read GetValueLongInt write SetValueLongInt;
  471. end;
  472. ////////////////////////////////////////////////////////////////////////////////
  473. //
  474. // TInDragLoopClipboardFormat
  475. //
  476. ////////////////////////////////////////////////////////////////////////////////
  477. TInShellDragLoopClipboardFormat = class(TCustomDWORDClipboardFormat)
  478. public
  479. function GetClipboardFormat: TClipFormat; override;
  480. property InShellDragLoop: boolean read GetValueBoolean write SetValueBoolean;
  481. end;
  482. ////////////////////////////////////////////////////////////////////////////////
  483. //
  484. // TTargetCLSIDClipboardFormat
  485. //
  486. ////////////////////////////////////////////////////////////////////////////////
  487. TTargetCLSIDClipboardFormat = class(TCustomSimpleClipboardFormat)
  488. private
  489. FCLSID: TCLSID;
  490. protected
  491. function ReadData(Value: pointer; Size: integer): boolean; override;
  492. function WriteData(Value: pointer; Size: integer): boolean; override;
  493. function GetSize: integer; override;
  494. public
  495. function GetClipboardFormat: TClipFormat; override;
  496. procedure Clear; override;
  497. function HasData: boolean; override;
  498. property CLSID: TCLSID read FCLSID write FCLSID;
  499. end;
  500. ////////////////////////////////////////////////////////////////////////////////
  501. ////////////////////////////////////////////////////////////////////////////////
  502. ////////////////////////////////////////////////////////////////////////////////
  503. ////////////////////////////////////////////////////////////////////////////////
  504. //
  505. // TTextDataFormat
  506. //
  507. ////////////////////////////////////////////////////////////////////////////////
  508. TTextDataFormat = class(TCustomDataFormat)
  509. private
  510. FText : string;
  511. protected
  512. procedure SetText(const Value: string);
  513. public
  514. function Assign(Source: TClipboardFormat): boolean; override;
  515. function AssignTo(Dest: TClipboardFormat): boolean; override;
  516. procedure Clear; override;
  517. function HasData: boolean; override;
  518. function NeedsData: boolean; override;
  519. property Text: string read FText write SetText;
  520. end;
  521. ////////////////////////////////////////////////////////////////////////////////
  522. //
  523. // TDataStreamDataFormat
  524. //
  525. ////////////////////////////////////////////////////////////////////////////////
  526. TDataStreamDataFormat = class(TCustomDataFormat)
  527. private
  528. FStreams : TStreamList;
  529. public
  530. constructor Create(AOwner: TDragDropComponent); override;
  531. destructor Destroy; override;
  532. procedure Clear; override;
  533. function HasData: boolean; override;
  534. function NeedsData: boolean; override;
  535. property Streams: TStreamList read FStreams;
  536. end;
  537. ////////////////////////////////////////////////////////////////////////////////
  538. //
  539. // TVirtualFileStreamDataFormat
  540. //
  541. ////////////////////////////////////////////////////////////////////////////////
  542. TVirtualFileStreamDataFormat = class(TCustomDataFormat)
  543. private
  544. FFileDescriptors: TMemoryList;
  545. FFileNames: TStrings;
  546. FFileContentsClipboardFormat: TFileContentsStreamOnDemandClipboardFormat;
  547. FFileGroupDescritorClipboardFormat: TFileGroupDescritorClipboardFormat;
  548. FHasContents: boolean;
  549. protected
  550. procedure SetFileNames(const Value: TStrings);
  551. function GetOnGetStream: TOnGetStreamEvent;
  552. procedure SetOnGetStream(const Value: TOnGetStreamEvent);
  553. public
  554. constructor Create(AOwner: TDragDropComponent); override;
  555. destructor Destroy; override;
  556. function Assign(Source: TClipboardFormat): boolean; override;
  557. function AssignTo(Dest: TClipboardFormat): boolean; override;
  558. procedure Clear; override;
  559. function HasData: boolean; override;
  560. function NeedsData: boolean; override;
  561. property FileDescriptors: TMemoryList read FFileDescriptors;
  562. property FileNames: TStrings read FFileNames write SetFileNames;
  563. property FileContentsClipboardFormat: TFileContentsStreamOnDemandClipboardFormat
  564. read FFileContentsClipboardFormat;
  565. property FileGroupDescritorClipboardFormat: TFileGroupDescritorClipboardFormat
  566. read FFileGroupDescritorClipboardFormat;
  567. property OnGetStream: TOnGetStreamEvent read GetOnGetStream write SetOnGetStream;
  568. end;
  569. ////////////////////////////////////////////////////////////////////////////////
  570. //
  571. // TFeedbackDataFormat
  572. //
  573. ////////////////////////////////////////////////////////////////////////////////
  574. // Data used for communication between source and target.
  575. // Only used by the drop source.
  576. ////////////////////////////////////////////////////////////////////////////////
  577. TFeedbackDataFormat = class(TCustomDataFormat)
  578. private
  579. FPreferredDropEffect: longInt;
  580. FPerformedDropEffect: longInt;
  581. FLogicalPerformedDropEffect: longInt;
  582. FPasteSucceded: longInt;
  583. FInShellDragLoop: boolean;
  584. FGotInShellDragLoop: boolean;
  585. FTargetCLSID: TCLSID;
  586. protected
  587. procedure SetInShellDragLoop(const Value: boolean);
  588. procedure SetPasteSucceded(const Value: longInt);
  589. procedure SetPerformedDropEffect(const Value: longInt);
  590. procedure SetPreferredDropEffect(const Value: longInt);
  591. procedure SetTargetCLSID(const Value: TCLSID);
  592. procedure SetLogicalPerformedDropEffect(const Value: Integer);
  593. public
  594. function Assign(Source: TClipboardFormat): boolean; override;
  595. function AssignTo(Dest: TClipboardFormat): boolean; override;
  596. procedure Clear; override;
  597. function HasData: boolean; override;
  598. function NeedsData: boolean; override;
  599. property PreferredDropEffect: longInt read FPreferredDropEffect
  600. write SetPreferredDropEffect;
  601. property PerformedDropEffect: longInt read FPerformedDropEffect
  602. write SetPerformedDropEffect;
  603. property LogicalPerformedDropEffect: longInt read FLogicalPerformedDropEffect
  604. write SetLogicalPerformedDropEffect;
  605. property PasteSucceded: longInt read FPasteSucceded write SetPasteSucceded;
  606. property InShellDragLoop: boolean read FInShellDragLoop
  607. write SetInShellDragLoop;
  608. property TargetCLSID: TCLSID read FTargetCLSID write SetTargetCLSID;
  609. end;
  610. ////////////////////////////////////////////////////////////////////////////////
  611. //
  612. // TGenericClipboardFormat & TGenericDataFormat
  613. //
  614. ////////////////////////////////////////////////////////////////////////////////
  615. // TGenericDataFormat is not used internally by the library, but can be used to
  616. // add support for new formats with a minimum of custom code.
  617. // Even though TGenericDataFormat represents the data as a string, it can be
  618. // used to transfer any kind of data.
  619. // TGenericClipboardFormat is used internally by TGenericDataFormat but can also
  620. // be used by other TCustomDataFormat descendants or as a base class for new
  621. // clipboard formats.
  622. // Note that you should not register TGenericClipboardFormat as compatible with
  623. // TGenericDataFormat.
  624. // To use TGenericDataFormat, all you need to do is instantiate it against
  625. // the desired component and register your custom clipboard formats:
  626. //
  627. // var
  628. // MyCustomData: TGenericDataFormat;
  629. //
  630. // MyCustomData := TGenericDataFormat.Create(DropTextTarget1);
  631. // MyCustomData.AddFormat('MyCustomFormat');
  632. //
  633. ////////////////////////////////////////////////////////////////////////////////
  634. TGenericDataFormat = class(TCustomDataFormat)
  635. private
  636. FData : string;
  637. protected
  638. function GetSize: integer;
  639. procedure DoSetData(const Value: string);
  640. public
  641. procedure Clear; override;
  642. function HasData: boolean; override;
  643. function NeedsData: boolean; override;
  644. procedure AddFormat(const AFormat: string);
  645. procedure SetDataHere(const AData; ASize: integer);
  646. function GetDataHere(var AData; ASize: integer): integer;
  647. property Data: string read FData write DoSetData;
  648. property Size: integer read GetSize;
  649. end;
  650. TGenericClipboardFormat = class(TCustomStringClipboardFormat)
  651. private
  652. FFormat: string;
  653. protected
  654. procedure SetClipboardFormatName(const Value: string); override;
  655. function GetClipboardFormatName: string; override;
  656. function GetClipboardFormat: TClipFormat; override;
  657. public
  658. function Assign(Source: TCustomDataFormat): boolean; override;
  659. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  660. property Data;
  661. end;
  662. ////////////////////////////////////////////////////////////////////////////////
  663. ////////////////////////////////////////////////////////////////////////////////
  664. //
  665. // IMPLEMENTATION
  666. //
  667. ////////////////////////////////////////////////////////////////////////////////
  668. ////////////////////////////////////////////////////////////////////////////////
  669. implementation
  670. uses
  671. DropSource,
  672. DropTarget,
  673. SysUtils;
  674. ////////////////////////////////////////////////////////////////////////////////
  675. //
  676. // TStreamList
  677. //
  678. ////////////////////////////////////////////////////////////////////////////////
  679. constructor TStreamList.Create;
  680. begin
  681. inherited Create;
  682. FStreams := TStringList.Create;
  683. end;
  684. destructor TStreamList.Destroy;
  685. begin
  686. Clear;
  687. FStreams.Free;
  688. inherited Destroy;
  689. end;
  690. procedure TStreamList.Changing;
  691. begin
  692. if (Assigned(OnChanging)) then
  693. OnChanging(Self);
  694. end;
  695. function TStreamList.GetStream(Index: integer): TStream;
  696. begin
  697. Result := TStream(FStreams.Objects[Index]);
  698. end;
  699. function TStreamList.Add(Stream: TStream): integer;
  700. begin
  701. Result := AddNamed(Stream, '');
  702. end;
  703. function TStreamList.AddNamed(Stream: TStream; Name: string): integer;
  704. begin
  705. Changing;
  706. Result := FStreams.AddObject(Name, Stream);
  707. end;
  708. function TStreamList.GetCount: integer;
  709. begin
  710. Result := FStreams.Count;
  711. end;
  712. procedure TStreamList.Assign(Value: TStreamList);
  713. begin
  714. Clear;
  715. FStreams.Assign(Value.Names);
  716. // Transfer ownership of objects
  717. Value.FStreams.Clear;
  718. end;
  719. procedure TStreamList.Delete(Index: integer);
  720. begin
  721. Changing;
  722. FStreams.Delete(Index);
  723. end;
  724. procedure TStreamList.Clear;
  725. var
  726. i : integer;
  727. begin
  728. Changing;
  729. for i := 0 to FStreams.Count-1 do
  730. if (FStreams.Objects[i] <> nil) then
  731. FStreams.Objects[i].Free;
  732. FStreams.Clear;
  733. end;
  734. ////////////////////////////////////////////////////////////////////////////////
  735. //
  736. // TInterfaceList
  737. //
  738. ////////////////////////////////////////////////////////////////////////////////
  739. constructor TInterfaceList.Create;
  740. begin
  741. inherited Create;
  742. FList := TStringList.Create;
  743. end;
  744. destructor TInterfaceList.Destroy;
  745. begin
  746. Clear;
  747. FList.Free;
  748. inherited Destroy;
  749. end;
  750. function TInterfaceList.Add(Item: IUnknown): integer;
  751. begin
  752. Result := AddNamed(Item, '');
  753. end;
  754. function TInterfaceList.AddNamed(Item: IUnknown; Name: string): integer;
  755. begin
  756. Changing;
  757. with FList do
  758. begin
  759. Result := AddObject(Name, nil);
  760. Objects[Result] := TObject(Item);
  761. Item._AddRef;
  762. end;
  763. end;
  764. procedure TInterfaceList.Changing;
  765. begin
  766. if (Assigned(OnChanging)) then
  767. OnChanging(Self);
  768. end;
  769. procedure TInterfaceList.Clear;
  770. var
  771. i : Integer;
  772. p : pointer;
  773. begin
  774. Changing;
  775. with FList do
  776. begin
  777. for i := 0 to Count - 1 do
  778. begin
  779. p := Objects[i];
  780. IUnknown(p) := nil;
  781. end;
  782. Clear;
  783. end;
  784. end;
  785. procedure TInterfaceList.Assign(Value: TInterfaceList);
  786. var
  787. i : Integer;
  788. begin
  789. Changing;
  790. for i := 0 to Value.Count - 1 do
  791. AddNamed(Value.Items[i], Value.Names[i]);
  792. end;
  793. procedure TInterfaceList.Delete(Index: integer);
  794. var
  795. p : pointer;
  796. begin
  797. Changing;
  798. with FList do
  799. begin
  800. p := Objects[Index];
  801. IUnknown(p) := nil;
  802. Delete(Index);
  803. end;
  804. end;
  805. function TInterfaceList.GetCount: integer;
  806. begin
  807. Result := FList.Count;
  808. end;
  809. function TInterfaceList.GetName(Index: integer): string;
  810. begin
  811. Result := FList[Index];
  812. end;
  813. function TInterfaceList.GetItem(Index: integer): IUnknown;
  814. var
  815. p : pointer;
  816. begin
  817. p := FList.Objects[Index];
  818. Result := IUnknown(p);
  819. end;
  820. ////////////////////////////////////////////////////////////////////////////////
  821. //
  822. // TStorageInterfaceList
  823. //
  824. ////////////////////////////////////////////////////////////////////////////////
  825. function TStorageInterfaceList.GetStorage(Index: integer): IStorage;
  826. begin
  827. Result := IStorage(Items[Index]);
  828. end;
  829. ////////////////////////////////////////////////////////////////////////////////
  830. //
  831. // TMemoryList
  832. //
  833. ////////////////////////////////////////////////////////////////////////////////
  834. function TMemoryList.Add(Item: Pointer): Integer;
  835. begin
  836. Result := FList.Add(Item);
  837. end;
  838. procedure TMemoryList.Clear;
  839. var
  840. i: integer;
  841. begin
  842. for i := FList.Count-1 downto 0 do
  843. Delete(i);
  844. end;
  845. constructor TMemoryList.Create;
  846. begin
  847. inherited Create;
  848. FList := TList.Create;
  849. end;
  850. procedure TMemoryList.Delete(Index: Integer);
  851. begin
  852. Freemem(FList[Index]);
  853. FList.Delete(Index);
  854. end;
  855. destructor TMemoryList.Destroy;
  856. begin
  857. FList.Free;
  858. inherited Destroy;
  859. end;
  860. function TMemoryList.Get(Index: Integer): Pointer;
  861. begin
  862. Result := FList[Index];
  863. end;
  864. function TMemoryList.GetCount: Integer;
  865. begin
  866. Result := FList.Count;
  867. end;
  868. ////////////////////////////////////////////////////////////////////////////////
  869. //
  870. // TFixedStreamAdapter
  871. //
  872. ////////////////////////////////////////////////////////////////////////////////
  873. function TFixedStreamAdapter.CopyTo(stm: IStream; cb: Largeint; out cbRead: Largeint;
  874. out cbWritten: Largeint): HResult;
  875. const
  876. MaxBufSize = 1024 * 1024; // 1mb
  877. var
  878. Buffer: Pointer;
  879. BufSize, BurstReadSize, BurstWriteSize: Integer;
  880. BytesRead, BytesWritten, BurstWritten: LongInt;
  881. begin
  882. Result := S_OK;
  883. BytesRead := 0;
  884. BytesWritten := 0;
  885. try
  886. if (cb < 0) then
  887. begin
  888. // Note: The folowing is a workaround for a design bug in either explorer
  889. // or the clipboard. See comment in TCustomSimpleClipboardFormat.DoSetData
  890. // for an explanation.
  891. if (Stream.Position = Stream.Size) then
  892. Stream.Position := 0;
  893. cb := Stream.Size - Stream.Position;
  894. end;
  895. if cb > MaxBufSize then
  896. BufSize := MaxBufSize
  897. else
  898. BufSize := Integer(cb);
  899. GetMem(Buffer, BufSize);
  900. try
  901. while cb > 0 do
  902. begin
  903. if cb > BufSize then
  904. BurstReadSize := BufSize
  905. else
  906. BurstReadSize := cb;
  907. BurstWriteSize := Stream.Read(Buffer^, BurstReadSize);
  908. if (BurstWriteSize = 0) then
  909. break;
  910. Inc(BytesRead, BurstWriteSize);
  911. BurstWritten := 0;
  912. Result := stm.Write(Buffer, BurstWriteSize, @BurstWritten);
  913. Inc(BytesWritten, BurstWritten);
  914. if (Result = S_OK) and (Integer(BurstWritten) <> BurstWriteSize) then
  915. Result := E_FAIL;
  916. if Result <> S_OK then
  917. Exit;
  918. Dec(cb, BurstWritten);
  919. end;
  920. finally
  921. FreeMem(Buffer);
  922. if (@cbWritten <> nil) then
  923. cbWritten := BytesWritten;
  924. if (@cbRead <> nil) then
  925. cbRead := BytesRead;
  926. end;
  927. except
  928. Result := E_UNEXPECTED;
  929. end;
  930. end;
  931. ////////////////////////////////////////////////////////////////////////////////
  932. //
  933. // TCustomSimpleClipboardFormat
  934. //
  935. ////////////////////////////////////////////////////////////////////////////////
  936. constructor TCustomSimpleClipboardFormat.Create;
  937. begin
  938. CreateFormat(TYMED_HGLOBAL or TYMED_ISTREAM);
  939. end;
  940. function TCustomSimpleClipboardFormat.DoGetData(ADataObject: IDataObject;
  941. const AMedium: TStgMedium): boolean;
  942. var
  943. Stream : IStream;
  944. StatStg : TStatStg;
  945. Size : integer;
  946. begin
  947. // Get size from HGlobal.
  948. if (AMedium.tymed and TYMED_HGLOBAL <> 0) then
  949. begin
  950. Size := GlobalSize(AMedium.HGlobal);
  951. Result := True;
  952. end else
  953. // Get size from IStream.
  954. if (AMedium.tymed and TYMED_ISTREAM <> 0) then
  955. begin
  956. Stream := IStream(AMedium.stm);
  957. Result := (Stream <> nil) and (Stream.Stat(StatStg, STATFLAG_NONAME) = S_OK);
  958. Size := StatStg.cbSize;
  959. Stream := nil; // Not really nescessary.
  960. end else
  961. begin
  962. Size := 0;
  963. Result := False;
  964. end;
  965. if (Result) and (Size > 0) then
  966. begin
  967. // Read the given amount of data.
  968. Result := DoGetDataSized(ADataObject, AMedium, Size);
  969. end;
  970. end;
  971. function TCustomSimpleClipboardFormat.DoGetDataSized(ADataObject: IDataObject;
  972. const AMedium: TStgMedium; Size: integer): boolean;
  973. var
  974. Buffer: pointer;
  975. Stream: IStream;
  976. Remaining: longInt;
  977. Chunk: longInt;
  978. pChunk: PChar;
  979. begin
  980. if (Size > 0) then
  981. begin
  982. (*
  983. ** In this method we prefer TYMED_HGLOBAL over TYMED_ISTREAM and thus check
  984. ** for TYMED_HGLOBAL first.
  985. *)
  986. // Read data from HGlobal
  987. if (AMedium.tymed and TYMED_HGLOBAL <> 0) then
  988. begin
  989. // Use global memory as buffer
  990. Buffer := GlobalLock(AMedium.HGlobal);
  991. try
  992. // Read data from buffer into object
  993. Result := (Buffer <> nil) and (ReadData(Buffer, Size));
  994. finally
  995. GlobalUnlock(AMedium.HGlobal);
  996. end;
  997. end else
  998. // Read data from IStream
  999. if (AMedium.tymed and TYMED_ISTREAM <> 0) then
  1000. begin
  1001. // Allocate buffer
  1002. GetMem(Buffer, Size);
  1003. try
  1004. // Read data from stream into buffer
  1005. Stream := IStream(AMedium.stm);
  1006. if (Stream <> nil) then
  1007. begin
  1008. Stream.Seek(0, STREAM_SEEK_SET, PLargeuint(nil)^);
  1009. Result := True;
  1010. Remaining := Size;
  1011. pChunk := Buffer;
  1012. while (Result) and (Remaining > 0) do
  1013. begin
  1014. Result := (Stream.Read(pChunk, Remaining, @Chunk) = S_OK);
  1015. if (Chunk = 0) then
  1016. break;
  1017. inc(pChunk, Chunk);
  1018. dec(Remaining, Chunk);
  1019. end;
  1020. Stream := nil; // Not really nescessary.
  1021. end else
  1022. Result := False;
  1023. // Transfer data from buffer into object.
  1024. Result := Result and (ReadData(Buffer, Size));
  1025. finally
  1026. FreeMem(Buffer);
  1027. end;
  1028. end else
  1029. Result := False;
  1030. end else
  1031. Result := False;
  1032. end;
  1033. function TCustomSimpleClipboardFormat.ReadDataInto(ADataObject: IDataObject;
  1034. const AMedium: TStgMedium; Buffer: pointer; Size: integer): boolean;
  1035. var
  1036. Stream: IStream;
  1037. p: pointer;
  1038. Remaining: longInt;
  1039. Chunk: longInt;
  1040. begin
  1041. Result := (Buffer <> nil) and (Size > 0);
  1042. if (Result) then
  1043. begin
  1044. // Read data from HGlobal
  1045. if (AMedium.tymed and TYMED_HGLOBAL <> 0) then
  1046. begin
  1047. p := GlobalLock(AMedium.HGlobal);
  1048. try
  1049. Result := (p <> nil);
  1050. if (Result) then
  1051. Move(p^, Buffer^, Size);
  1052. finally
  1053. GlobalUnlock(AMedium.HGlobal);
  1054. end;
  1055. end else
  1056. // Read data from IStream
  1057. if (AMedium.tymed and TYMED_ISTREAM <> 0) then
  1058. begin
  1059. Stream := IStream(AMedium.stm);
  1060. if (Stream <> nil) then
  1061. begin
  1062. Stream.Seek(0, STREAM_SEEK_SET, PLargeuint(nil)^);
  1063. Remaining := Size;
  1064. while (Result) and (Remaining > 0) do
  1065. begin
  1066. Result := (Stream.Read(Buffer, Remaining, @Chunk) = S_OK);
  1067. if (Chunk = 0) then
  1068. break;
  1069. inc(PChar(Buffer), Chunk);
  1070. dec(Remaining, Chunk);
  1071. end;
  1072. end else
  1073. Result := False;
  1074. end else
  1075. Result := False;
  1076. end;
  1077. end;
  1078. function TCustomSimpleClipboardFormat.DoSetData(const FormatEtcIn: TFormatEtc;
  1079. var AMedium: TStgMedium): boolean;
  1080. var
  1081. p: pointer;
  1082. Size: integer;
  1083. Stream: TMemoryStream;
  1084. // Warning: TStreamAdapter.CopyTo is broken!
  1085. StreamAdapter: TStreamAdapter;
  1086. begin
  1087. Result := False;
  1088. Size := GetSize;
  1089. if (Size <= 0) then
  1090. exit;
  1091. if (FormatEtcIn.tymed and TYMED_ISTREAM <> 0) then
  1092. begin
  1093. Stream := TMemoryStream.Create;
  1094. StreamAdapter := TFixedStreamAdapter.Create(Stream, soOwned);
  1095. try
  1096. Stream.Size := Size;
  1097. Result := WriteData(Stream.Memory, Size);
  1098. // Note: Conflicting information on which of the following two are correct:
  1099. //
  1100. // 1) Stream.Position := Size;
  1101. //
  1102. // 2) Stream.Position := 0;
  1103. //
  1104. // #1 is required for clipboard operations to succeed; The clipboard uses
  1105. // a Seek(0, STREAM_SEEK_CUR) to determine the size of the stream.
  1106. //
  1107. // #2 is required for shell operations to succeed; The shell uses a
  1108. // Read(-1) to read all of the stream.
  1109. //
  1110. // This library uses a Stream.Stat to determine the size of the stream and
  1111. // then reads from start to end of stream.
  1112. //
  1113. // Since we use #1 (see below), we work around #2 in
  1114. // TFixedStreamAdapter.CopyTo.
  1115. if (Result) then
  1116. begin
  1117. Stream.Position := Size;
  1118. IStream(AMedium.stm) := StreamAdapter as IStream;
  1119. end;
  1120. except
  1121. Result := False;
  1122. end;
  1123. if (not Result) then
  1124. begin
  1125. StreamAdapter.Free;
  1126. AMedium.stm := nil;
  1127. end else
  1128. AMedium.tymed := TYMED_ISTREAM;
  1129. end else
  1130. if (FormatEtcIn.tymed and TYMED_HGLOBAL <> 0) then
  1131. begin
  1132. AMedium.hGlobal := GlobalAlloc(GMEM_SHARE or GHND, Size);
  1133. if (AMedium.hGlobal = 0) then
  1134. exit;
  1135. try
  1136. p := GlobalLock(AMedium.hGlobal);
  1137. try
  1138. Result := (p <> nil) and WriteData(p, Size);
  1139. finally
  1140. GlobalUnlock(AMedium.hGlobal);
  1141. end;
  1142. except
  1143. Result := False;
  1144. end;
  1145. if (not Result) then
  1146. begin
  1147. GlobalFree(AMedium.hGlobal);
  1148. AMedium.hGlobal := 0;
  1149. end else
  1150. AMedium.tymed := TYMED_HGLOBAL;
  1151. end else
  1152. Result := False;
  1153. end;
  1154. ////////////////////////////////////////////////////////////////////////////////
  1155. //
  1156. // TCustomStringClipboardFormat
  1157. //
  1158. ////////////////////////////////////////////////////////////////////////////////
  1159. procedure TCustomStringClipboardFormat.Clear;
  1160. begin
  1161. FData := '';
  1162. end;
  1163. function TCustomStringClipboardFormat.HasData: boolean;
  1164. begin
  1165. Result := (FData <> '');
  1166. end;
  1167. function TCustomStringClipboardFormat.ReadData(Value: pointer;
  1168. Size: integer): boolean;
  1169. begin
  1170. SetLength(FData, Size);
  1171. Move(Value^, PChar(FData)^, Size);
  1172. // IE adds a lot of trailing zeroes which is included in the string length.
  1173. // To avoid confusion, we trim all trailing zeroes but the last (which is
  1174. // managed automatically by Delphi).
  1175. // Note that since this work around, if applied generally, would mean that we
  1176. // couldn't use this class to handle arbitrary binary data (which might
  1177. // include zeroes), we are required to explicitly enable it in the classes
  1178. // where we need it (e.g. all TCustomTextClipboardFormat descedants).
  1179. if (FTrimZeroes) then
  1180. SetLength(FData, Length(PChar(FData)));
  1181. Result := True;
  1182. end;
  1183. function TCustomStringClipboardFormat.WriteData(Value: pointer;
  1184. Size: integer): boolean;
  1185. begin
  1186. // Transfer string including terminating zero if requested.
  1187. Result := (Size <= Length(FData)+1);
  1188. if (Result) then
  1189. Move(PChar(FData)^, Value^, Size);
  1190. end;
  1191. function TCustomStringClipboardFormat.GetSize: integer;
  1192. begin
  1193. Result := Length(FData);
  1194. end;
  1195. function TCustomStringClipboardFormat.GetString: string;
  1196. begin
  1197. Result := FData;
  1198. end;
  1199. procedure TCustomStringClipboardFormat.SetString(const Value: string);
  1200. begin
  1201. FData := Value;
  1202. end;
  1203. ////////////////////////////////////////////////////////////////////////////////
  1204. //
  1205. // TCustomStringListClipboardFormat
  1206. //
  1207. ////////////////////////////////////////////////////////////////////////////////
  1208. constructor TCustomStringListClipboardFormat.Create;
  1209. begin
  1210. inherited Create;
  1211. FLines := TStringList.Create
  1212. end;
  1213. destructor TCustomStringListClipboardFormat.Destroy;
  1214. begin
  1215. FLines.Free;
  1216. inherited Destroy;
  1217. end;
  1218. procedure TCustomStringListClipboardFormat.Clear;
  1219. begin
  1220. FLines.Clear;
  1221. end;
  1222. function TCustomStringListClipboardFormat.HasData: boolean;
  1223. begin
  1224. Result := (FLines.Count > 0);
  1225. end;
  1226. function TCustomStringListClipboardFormat.ReadData(Value: pointer;
  1227. Size: integer): boolean;
  1228. var
  1229. s : UTF8String;// string;
  1230. begin
  1231. SetLength(s, Size+1);
  1232. Move(Value^, PChar(s)^, Size);
  1233. s[Size + 1] := #0;
  1234. FLines.Text := Utf8ToAnsi(s);
  1235. Result := True;
  1236. end;
  1237. function TCustomStringListClipboardFormat.WriteData(Value: pointer;
  1238. Size: integer): boolean;
  1239. var
  1240. s : string;
  1241. begin
  1242. s := FLines.Text;
  1243. Result := (Size = Length(s)+1);
  1244. if (Result) then
  1245. Move(PChar(s)^, Value^, Size);
  1246. end;
  1247. function TCustomStringListClipboardFormat.GetSize: integer;
  1248. begin
  1249. Result := Length(FLines.Text)+1;
  1250. end;
  1251. function TCustomStringListClipboardFormat.GetLines: TStrings;
  1252. begin
  1253. Result := FLines;
  1254. end;
  1255. ////////////////////////////////////////////////////////////////////////////////
  1256. //
  1257. // TCustomTextClipboardFormat
  1258. //
  1259. ////////////////////////////////////////////////////////////////////////////////
  1260. constructor TCustomTextClipboardFormat.Create;
  1261. begin
  1262. inherited Create;
  1263. TrimZeroes := True;
  1264. end;
  1265. function TCustomTextClipboardFormat.GetSize: integer;
  1266. begin
  1267. Result := inherited GetSize;
  1268. // Unless the data is already zero terminated, we add a byte to include
  1269. // the string's implicit terminating zero.
  1270. if (Data[Result] <> #0) then
  1271. inc(Result);
  1272. end;
  1273. ////////////////////////////////////////////////////////////////////////////////
  1274. //
  1275. // TCustomWideTextClipboardFormat
  1276. //
  1277. ////////////////////////////////////////////////////////////////////////////////
  1278. procedure TCustomWideTextClipboardFormat.Clear;
  1279. begin
  1280. FText := '';
  1281. end;
  1282. function TCustomWideTextClipboardFormat.HasData: boolean;
  1283. begin
  1284. Result := (FText <> '');
  1285. end;
  1286. function TCustomWideTextClipboardFormat.ReadData(Value: pointer;
  1287. Size: integer): boolean;
  1288. begin
  1289. SetLength(FText, Size div 2);
  1290. Move(Value^, PWideChar(FText)^, Size);
  1291. Result := True;
  1292. end;
  1293. function TCustomWideTextClipboardFormat.WriteData(Value: pointer;
  1294. Size: integer): boolean;
  1295. begin
  1296. Result := (Size <= (Length(FText)+1)*2);
  1297. if (Result) then
  1298. Move(PWideChar(FText)^, Value^, Size);
  1299. end;
  1300. function TCustomWideTextClipboardFormat.GetSize: integer;
  1301. begin
  1302. Result := Length(FText)*2;
  1303. // Unless the data is already zero terminated, we add two bytes to include
  1304. // the string's implicit terminating zero.
  1305. if (FText[Result] <> #0) then
  1306. inc(Result, 2);
  1307. end;
  1308. function TCustomWideTextClipboardFormat.GetText: WideString;
  1309. begin
  1310. Result := FText;
  1311. end;
  1312. procedure TCustomWideTextClipboardFormat.SetText(const Value: WideString);
  1313. begin
  1314. FText := Value;
  1315. end;
  1316. ////////////////////////////////////////////////////////////////////////////////
  1317. //
  1318. // TTextClipboardFormat
  1319. //
  1320. ////////////////////////////////////////////////////////////////////////////////
  1321. function TTextClipboardFormat.GetClipboardFormat: TClipFormat;
  1322. begin
  1323. Result := CF_TEXT;
  1324. end;
  1325. ////////////////////////////////////////////////////////////////////////////////
  1326. //
  1327. // TCustomDWORDClipboardFormat
  1328. //
  1329. ////////////////////////////////////////////////////////////////////////////////
  1330. function TCustomDWORDClipboardFormat.ReadData(Value: pointer;
  1331. Size: integer): boolean;
  1332. begin
  1333. FValue := PDWORD(Value)^;
  1334. Result := True;
  1335. end;
  1336. function TCustomDWORDClipboardFormat.WriteData(Value: pointer;
  1337. Size: integer): boolean;
  1338. begin
  1339. Result := (Size = SizeOf(DWORD));
  1340. if (Result) then
  1341. PDWORD(Value)^ := FValue;
  1342. end;
  1343. function TCustomDWORDClipboardFormat.GetSize: integer;
  1344. begin
  1345. Result := SizeOf(DWORD);
  1346. end;
  1347. procedure TCustomDWORDClipboardFormat.Clear;
  1348. begin
  1349. FValue := 0;
  1350. end;
  1351. function TCustomDWORDClipboardFormat.GetValueDWORD: DWORD;
  1352. begin
  1353. Result := FValue;
  1354. end;
  1355. procedure TCustomDWORDClipboardFormat.SetValueDWORD(Value: DWORD);
  1356. begin
  1357. FValue := Value;
  1358. end;
  1359. function TCustomDWORDClipboardFormat.GetValueInteger: integer;
  1360. begin
  1361. Result := integer(FValue);
  1362. end;
  1363. procedure TCustomDWORDClipboardFormat.SetValueInteger(Value: integer);
  1364. begin
  1365. FValue := DWORD(Value);
  1366. end;
  1367. function TCustomDWORDClipboardFormat.GetValueLongInt: longInt;
  1368. begin
  1369. Result := longInt(FValue);
  1370. end;
  1371. procedure TCustomDWORDClipboardFormat.SetValueLongInt(Value: longInt);
  1372. begin
  1373. FValue := DWORD(Value);
  1374. end;
  1375. function TCustomDWORDClipboardFormat.GetValueBoolean: boolean;
  1376. begin
  1377. Result := (FValue <> 0);
  1378. end;
  1379. procedure TCustomDWORDClipboardFormat.SetValueBoolean(Value: boolean);
  1380. begin
  1381. FValue := ord(Value);
  1382. end;
  1383. ////////////////////////////////////////////////////////////////////////////////
  1384. //
  1385. // TFileGroupDescritorClipboardFormat
  1386. //
  1387. ////////////////////////////////////////////////////////////////////////////////
  1388. var
  1389. CF_FILEGROUPDESCRIPTOR: TClipFormat = 0;
  1390. function TFileGroupDescritorClipboardFormat.GetClipboardFormat: TClipFormat;
  1391. begin
  1392. if (CF_FILEGROUPDESCRIPTOR = 0) then
  1393. CF_FILEGROUPDESCRIPTOR := RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
  1394. Result := CF_FILEGROUPDESCRIPTOR;
  1395. end;
  1396. destructor TFileGroupDescritorClipboardFormat.Destroy;
  1397. begin
  1398. Clear;
  1399. inherited Destroy;
  1400. end;
  1401. procedure TFileGroupDescritorClipboardFormat.Clear;
  1402. begin
  1403. if (FFileGroupDescriptor <> nil) then
  1404. begin
  1405. FreeMem(FFileGroupDescriptor);
  1406. FFileGroupDescriptor := nil;
  1407. end;
  1408. end;
  1409. function TFileGroupDescritorClipboardFormat.HasData: boolean;
  1410. begin
  1411. Result := (FFileGroupDescriptor <> nil) and (FFileGroupDescriptor^.cItems <> 0);
  1412. end;
  1413. procedure TFileGroupDescritorClipboardFormat.CopyFrom(AFileGroupDescriptor: PFileGroupDescriptor);
  1414. var
  1415. Size : integer;
  1416. begin
  1417. Clear;
  1418. if (AFileGroupDescriptor <> nil) then
  1419. begin
  1420. Size := SizeOf(UINT) + AFileGroupDescriptor^.cItems * SizeOf(TFileDescriptor);
  1421. GetMem(FFileGroupDescriptor, Size);
  1422. Move(AFileGroupDescriptor^, FFileGroupDescriptor^, Size);
  1423. end;
  1424. end;
  1425. function TFileGroupDescritorClipboardFormat.GetSize: integer;
  1426. begin
  1427. if (FFileGroupDescriptor <> nil) then
  1428. Result := SizeOf(UINT) + FFileGroupDescriptor^.cItems * SizeOf(TFileDescriptor)
  1429. else
  1430. Result := 0;
  1431. end;
  1432. function TFileGroupDescritorClipboardFormat.ReadData(Value: pointer;
  1433. Size: integer): boolean;
  1434. begin
  1435. // Validate size against count
  1436. Result :=
  1437. (Size - SizeOf(UINT)) DIV SizeOf(TFileDescriptor) = integer(PFileGroupDescriptor(Value)^.cItems);
  1438. if (Result) then
  1439. CopyFrom(PFileGroupDescriptor(Value));
  1440. end;
  1441. function TFileGroupDescritorClipboardFormat.WriteData(Value: pointer;
  1442. Size: integer): boolean;
  1443. begin
  1444. // Validate size against count
  1445. Result := (FFileGroupDescriptor <> nil) and
  1446. ((Size - SizeOf(UINT)) DIV SizeOf(TFileDescriptor) = integer(FFileGroupDescriptor^.cItems));
  1447. if (Result) then
  1448. Move(FFileGroupDescriptor^, Value^, Size);
  1449. end;
  1450. ////////////////////////////////////////////////////////////////////////////////
  1451. //
  1452. // TFileGroupDescritorWClipboardFormat
  1453. //
  1454. ////////////////////////////////////////////////////////////////////////////////
  1455. var
  1456. CF_FILEGROUPDESCRIPTORW: TClipFormat = 0;
  1457. function TFileGroupDescritorWClipboardFormat.GetClipboardFormat: TClipFormat;
  1458. begin
  1459. if (CF_FILEGROUPDESCRIPTORW = 0) then
  1460. CF_FILEGROUPDESCRIPTORW := RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
  1461. Result := CF_FILEGROUPDESCRIPTORW;
  1462. end;
  1463. destructor TFileGroupDescritorWClipboardFormat.Destroy;
  1464. begin
  1465. Clear;
  1466. inherited Destroy;
  1467. end;
  1468. procedure TFileGroupDescritorWClipboardFormat.Clear;
  1469. begin
  1470. if (FFileGroupDescriptor <> nil) then
  1471. begin
  1472. FreeMem(FFileGroupDescriptor);
  1473. FFileGroupDescriptor := nil;
  1474. end;
  1475. end;
  1476. function TFileGroupDescritorWClipboardFormat.HasData: boolean;
  1477. begin
  1478. Result := (FFileGroupDescriptor <> nil) and (FFileGroupDescriptor^.cItems <> 0);
  1479. end;
  1480. procedure TFileGroupDescritorWClipboardFormat.CopyFrom(AFileGroupDescriptor: PFileGroupDescriptorW);
  1481. var
  1482. Size : integer;
  1483. begin
  1484. Clear;
  1485. if (AFileGroupDescriptor <> nil) then
  1486. begin
  1487. Size := SizeOf(UINT) + AFileGroupDescriptor^.cItems * SizeOf(TFileDescriptorW);
  1488. GetMem(FFileGroupDescriptor, Size);
  1489. Move(AFileGroupDescriptor^, FFileGroupDescriptor^, Size);
  1490. end;
  1491. end;
  1492. function TFileGroupDescritorWClipboardFormat.GetSize: integer;
  1493. begin
  1494. if (FFileGroupDescriptor <> nil) then
  1495. Result := SizeOf(UINT) + FFileGroupDescriptor^.cItems * SizeOf(TFileDescriptorW)
  1496. else
  1497. Result := 0;
  1498. end;
  1499. function TFileGroupDescritorWClipboardFormat.ReadData(Value: pointer;
  1500. Size: integer): boolean;
  1501. begin
  1502. // Validate size against count
  1503. Result :=
  1504. (Size - SizeOf(UINT)) DIV SizeOf(TFileDescriptorW) = integer(PFileGroupDescriptor(Value)^.cItems);
  1505. if (Result) then
  1506. CopyFrom(PFileGroupDescriptorW(Value));
  1507. end;
  1508. function TFileGroupDescritorWClipboardFormat.WriteData(Value: pointer;
  1509. Size: integer): boolean;
  1510. begin
  1511. // Validate size against count
  1512. Result := (FFileGroupDescriptor <> nil) and
  1513. ((Size - SizeOf(UINT)) DIV SizeOf(TFileDescriptorW) = integer(FFileGroupDescriptor^.cItems));
  1514. if (Result) then
  1515. Move(FFileGroupDescriptor^, Value^, Size);
  1516. end;
  1517. ////////////////////////////////////////////////////////////////////////////////
  1518. //
  1519. // TFileContentsClipboardFormat
  1520. //
  1521. ////////////////////////////////////////////////////////////////////////////////
  1522. var
  1523. CF_FILECONTENTS: TClipFormat = 0;
  1524. constructor TFileContentsClipboardFormat.Create;
  1525. begin
  1526. inherited Create;
  1527. FFormatEtc.lindex := 0;
  1528. end;
  1529. function TFileContentsClipboardFormat.GetClipboardFormat: TClipFormat;
  1530. begin
  1531. if (CF_FILECONTENTS = 0) then
  1532. CF_FILECONTENTS := RegisterClipboardFormat(CFSTR_FILECONTENTS);
  1533. Result := CF_FILECONTENTS;
  1534. end;
  1535. ////////////////////////////////////////////////////////////////////////////////
  1536. //
  1537. // TFileContentsStreamClipboardFormat
  1538. //
  1539. ////////////////////////////////////////////////////////////////////////////////
  1540. constructor TFileContentsStreamClipboardFormat.Create;
  1541. begin
  1542. CreateFormat(TYMED_ISTREAM);
  1543. FStreams := TStreamList.Create;
  1544. end;
  1545. destructor TFileContentsStreamClipboardFormat.Destroy;
  1546. begin
  1547. Clear;
  1548. FStreams.Free;
  1549. inherited Destroy;
  1550. end;
  1551. function TFileContentsStreamClipboardFormat.GetClipboardFormat: TClipFormat;
  1552. begin
  1553. if (CF_FILECONTENTS = 0) then
  1554. CF_FILECONTENTS := RegisterClipboardFormat(CFSTR_FILECONTENTS);
  1555. Result := CF_FILECONTENTS;
  1556. end;
  1557. procedure TFileContentsStreamClipboardFormat.Clear;
  1558. begin
  1559. FStreams.Clear;
  1560. end;
  1561. function TFileContentsStreamClipboardFormat.HasData: boolean;
  1562. begin
  1563. Result := (FStreams.Count > 0);
  1564. end;
  1565. function TFileContentsStreamClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  1566. begin
  1567. Result := True;
  1568. if (Dest is TDataStreamDataFormat) then
  1569. begin
  1570. TDataStreamDataFormat(Dest).Streams.Assign(Streams);
  1571. end else
  1572. Result := inherited AssignTo(Dest);
  1573. end;
  1574. {$IFOPT R+}
  1575. {$DEFINE R_PLUS}
  1576. {$RANGECHECKS OFF}
  1577. {$ENDIF}
  1578. function TFileContentsStreamClipboardFormat.GetData(DataObject: IDataObject): boolean;
  1579. var
  1580. FGD: TFileGroupDescritorClipboardFormat;
  1581. Count: integer;
  1582. Medium: TStgMedium;
  1583. Stream: IStream;
  1584. Name: string;
  1585. MemStream: TMemoryStream;
  1586. StatStg: TStatStg;
  1587. Size: longInt;
  1588. Remaining: longInt;
  1589. pChunk: PChar;
  1590. begin
  1591. Result := False;
  1592. Clear;
  1593. FGD := TFileGroupDescritorClipboardFormat.Create;
  1594. try
  1595. if (FGD.GetData(DataObject)) then
  1596. begin
  1597. // Multiple objects, retrieve one at a time
  1598. Count := FGD.FileGroupDescriptor^.cItems;
  1599. FFormatEtc.lindex := 0;
  1600. end else
  1601. begin
  1602. // Single object, retrieve "all" at once
  1603. Count := 0;
  1604. FFormatEtc.lindex := -1;
  1605. Name := '';
  1606. end;
  1607. while (FFormatEtc.lindex < Count) do
  1608. begin
  1609. if (DataObject.GetData(FormatEtc, Medium) <> S_OK) then
  1610. break;
  1611. try
  1612. inc(FFormatEtc.lindex);
  1613. if (Medium.tymed <> TYMED_ISTREAM) then
  1614. continue;
  1615. Stream := IStream(Medium.stm);
  1616. Stream.Stat(StatStg, STATFLAG_NONAME);
  1617. MemStream := TMemoryStream.Create;
  1618. try
  1619. Remaining := StatStg.cbSize;
  1620. MemStream.Size := Remaining;
  1621. pChunk := MemStream.Memory;
  1622. while (Remaining > 0) do
  1623. begin
  1624. if (Stream.Read(pChunk, Remaining, @Size) <> S_OK) or
  1625. (Size = 0) then
  1626. break;
  1627. inc(pChunk, Size);
  1628. dec(Remaining, Size);
  1629. end;
  1630. if (FFormatEtc.lindex > 0) then
  1631. Name := FGD.FileGroupDescriptor^.fgd[FFormatEtc.lindex-1].cFileName;
  1632. Streams.AddNamed(MemStream, Name);
  1633. except
  1634. MemStream.Free;
  1635. raise;
  1636. end;
  1637. Stream := nil;
  1638. Result := True;
  1639. finally
  1640. ReleaseStgMedium(Medium);
  1641. end;
  1642. end;
  1643. finally
  1644. FGD.Free;
  1645. end;
  1646. end;
  1647. {$IFDEF R_PLUS}
  1648. {$RANGECHECKS ON}
  1649. {$UNDEF R_PLUS}
  1650. {$ENDIF}
  1651. ////////////////////////////////////////////////////////////////////////////////
  1652. //
  1653. // TFileContentsStreamOnDemandClipboardFormat
  1654. //
  1655. ////////////////////////////////////////////////////////////////////////////////
  1656. constructor TFileContentsStreamOnDemandClipboardFormat.Create;
  1657. begin
  1658. CreateFormat(TYMED_ISTREAM);
  1659. end;
  1660. destructor TFileContentsStreamOnDemandClipboardFormat.Destroy;
  1661. begin
  1662. Clear;
  1663. inherited Destroy;
  1664. end;
  1665. function TFileContentsStreamOnDemandClipboardFormat.GetClipboardFormat: TClipFormat;
  1666. begin
  1667. if (CF_FILECONTENTS = 0) then
  1668. CF_FILECONTENTS := RegisterClipboardFormat(CFSTR_FILECONTENTS);
  1669. Result := CF_FILECONTENTS;
  1670. end;
  1671. procedure TFileContentsStreamOnDemandClipboardFormat.Clear;
  1672. begin
  1673. FGotData := False;
  1674. FDataRequested := False;
  1675. end;
  1676. function TFileContentsStreamOnDemandClipboardFormat.HasData: boolean;
  1677. begin
  1678. Result := FGotData or FDataRequested;
  1679. end;
  1680. function TFileContentsStreamOnDemandClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  1681. begin
  1682. if (Dest is TVirtualFileStreamDataFormat) then
  1683. begin
  1684. Result := True
  1685. end else
  1686. Result := inherited AssignTo(Dest);
  1687. end;
  1688. function TFileContentsStreamOnDemandClipboardFormat.Assign(
  1689. Source: TCustomDataFormat): boolean;
  1690. begin
  1691. if (Source is TVirtualFileStreamDataFormat) then
  1692. begin
  1693. // Acknowledge that we can offer the requested data, but defer the actual
  1694. // data transfer.
  1695. FDataRequested := True;
  1696. Result := True
  1697. end else
  1698. Result := inherited Assign(Source);
  1699. end;
  1700. function TFileContentsStreamOnDemandClipboardFormat.DoSetData(
  1701. const FormatEtcIn: TFormatEtc; var AMedium: TStgMedium): boolean;
  1702. var
  1703. Stream : IStream;
  1704. begin
  1705. if (Assigned(FOnGetStream)) and (FormatEtcIn.tymed and TYMED_ISTREAM <> 0) and
  1706. (FormatEtcIn.lindex <> -1) then
  1707. begin
  1708. FOnGetStream(Self, FormatEtcIn.lindex, Stream);
  1709. if (Stream <> nil) then
  1710. begin
  1711. IStream(AMedium.stm) := Stream;
  1712. AMedium.tymed := TYMED_ISTREAM;
  1713. Result := True;
  1714. end else
  1715. Result := False;
  1716. end else
  1717. Result := False;
  1718. end;
  1719. function TFileContentsStreamOnDemandClipboardFormat.GetData(DataObject: IDataObject): boolean;
  1720. begin
  1721. // Flag that data has been offered to us, but defer the actual data transfer.
  1722. FGotData := True;
  1723. Result := True;
  1724. end;
  1725. function TFileContentsStreamOnDemandClipboardFormat.GetStream(Index: integer): IStream;
  1726. var
  1727. Medium : TStgMedium;
  1728. begin
  1729. Result := nil;
  1730. FFormatEtc.lindex := Index;
  1731. // Get an IStream interface from the source.
  1732. if ((DataFormat.Owner as TCustomDroptarget).DataObject.GetData(FormatEtc,
  1733. Medium) = S_OK) and (Medium.tymed = TYMED_ISTREAM) then
  1734. try
  1735. Result := IStream(Medium.stm);
  1736. finally
  1737. ReleaseStgMedium(Medium);
  1738. end;
  1739. end;
  1740. ////////////////////////////////////////////////////////////////////////////////
  1741. //
  1742. // TFileContentsStorageClipboardFormat
  1743. //
  1744. ////////////////////////////////////////////////////////////////////////////////
  1745. constructor TFileContentsStorageClipboardFormat.Create;
  1746. begin
  1747. CreateFormat(TYMED_ISTORAGE);
  1748. FStorages := TStorageInterfaceList.Create;
  1749. end;
  1750. destructor TFileContentsStorageClipboardFormat.Destroy;
  1751. begin
  1752. Clear;
  1753. FStorages.Free;
  1754. inherited Destroy;
  1755. end;
  1756. function TFileContentsStorageClipboardFormat.GetClipboardFormat: TClipFormat;
  1757. begin
  1758. if (CF_FILECONTENTS = 0) then
  1759. CF_FILECONTENTS := RegisterClipboardFormat(CFSTR_FILECONTENTS);
  1760. Result := CF_FILECONTENTS;
  1761. end;
  1762. procedure TFileContentsStorageClipboardFormat.Clear;
  1763. begin
  1764. FStorages.Clear;
  1765. end;
  1766. function TFileContentsStorageClipboardFormat.HasData: boolean;
  1767. begin
  1768. Result := (FStorages.Count > 0);
  1769. end;
  1770. function TFileContentsStorageClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  1771. begin
  1772. (*
  1773. Result := True;
  1774. if (Dest is TDataStreamDataFormat) then
  1775. begin
  1776. TDataStreamDataFormat(Dest).Streams.Assign(Streams);
  1777. end else
  1778. *)
  1779. Result := inherited AssignTo(Dest);
  1780. end;
  1781. {$IFOPT R+}
  1782. {$DEFINE R_PLUS}
  1783. {$RANGECHECKS OFF}
  1784. {$ENDIF}
  1785. function TFileContentsStorageClipboardFormat.GetData(DataObject: IDataObject): boolean;
  1786. var
  1787. FGD : TFileGroupDescritorClipboardFormat;
  1788. Count : integer;
  1789. Medium : TStgMedium;
  1790. Storage : IStorage;
  1791. Name : string;
  1792. begin
  1793. Result := False;
  1794. Clear;
  1795. FGD := TFileGroupDescritorClipboardFormat.Create;
  1796. try
  1797. if (FGD.GetData(DataObject)) then
  1798. begin
  1799. // Multiple objects, retrieve one at a time
  1800. Count := FGD.FileGroupDescriptor^.cItems;
  1801. FFormatEtc.lindex := 0;
  1802. end else
  1803. begin
  1804. // Single object, retrieve "all" at once
  1805. Count := 0;
  1806. FFormatEtc.lindex := -1;
  1807. Name := '';
  1808. end;
  1809. while (FFormatEtc.lindex < Count) do
  1810. begin
  1811. if (DataObject.GetData(FormatEtc, Medium) <> S_OK) then
  1812. break;
  1813. try
  1814. inc(FFormatEtc.lindex);
  1815. if (Medium.tymed <> TYMED_ISTORAGE) then
  1816. continue;
  1817. Storage := IStorage(Medium.stg);
  1818. if (FFormatEtc.lindex > 0) then
  1819. Name := FGD.FileGroupDescriptor^.fgd[FFormatEtc.lindex-1].cFileName;
  1820. Storages.AddNamed(Storage, Name);
  1821. Storage := nil;
  1822. Result := True;
  1823. finally
  1824. ReleaseStgMedium(Medium);
  1825. end;
  1826. end;
  1827. finally
  1828. FGD.Free;
  1829. end;
  1830. end;
  1831. {$IFDEF R_PLUS}
  1832. {$RANGECHECKS ON}
  1833. {$UNDEF R_PLUS}
  1834. {$ENDIF}
  1835. ////////////////////////////////////////////////////////////////////////////////
  1836. //
  1837. // TPreferredDropEffectClipboardFormat
  1838. //
  1839. ////////////////////////////////////////////////////////////////////////////////
  1840. var
  1841. CF_PREFERREDDROPEFFECT: TClipFormat = 0;
  1842. // GetClassClipboardFormat is used by TCustomDropTarget.GetPreferredDropEffect
  1843. class function TPreferredDropEffectClipboardFormat.GetClassClipboardFormat: TClipFormat;
  1844. begin
  1845. if (CF_PREFERREDDROPEFFECT = 0) then
  1846. CF_PREFERREDDROPEFFECT := RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
  1847. Result := CF_PREFERREDDROPEFFECT;
  1848. end;
  1849. function TPreferredDropEffectClipboardFormat.GetClipboardFormat: TClipFormat;
  1850. begin
  1851. Result := GetClassClipboardFormat;
  1852. end;
  1853. function TPreferredDropEffectClipboardFormat.HasData: boolean;
  1854. begin
  1855. Result := True; //(Value <> DROPEFFECT_NONE);
  1856. end;
  1857. ////////////////////////////////////////////////////////////////////////////////
  1858. //
  1859. // TPerformedDropEffectClipboardFormat
  1860. //
  1861. ////////////////////////////////////////////////////////////////////////////////
  1862. var
  1863. CF_PERFORMEDDROPEFFECT: TClipFormat = 0;
  1864. function TPerformedDropEffectClipboardFormat.GetClipboardFormat: TClipFormat;
  1865. begin
  1866. if (CF_PERFORMEDDROPEFFECT = 0) then
  1867. CF_PERFORMEDDROPEFFECT := RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
  1868. Result := CF_PERFORMEDDROPEFFECT;
  1869. end;
  1870. ////////////////////////////////////////////////////////////////////////////////
  1871. //
  1872. // TLogicalPerformedDropEffectClipboardFormat
  1873. //
  1874. ////////////////////////////////////////////////////////////////////////////////
  1875. var
  1876. CF_LOGICALPERFORMEDDROPEFFECT: TClipFormat = 0;
  1877. function TLogicalPerformedDropEffectClipboardFormat.GetClipboardFormat: TClipFormat;
  1878. begin
  1879. if (CF_LOGICALPERFORMEDDROPEFFECT = 0) then
  1880. CF_LOGICALPERFORMEDDROPEFFECT := RegisterClipboardFormat('Logical Performed DropEffect'); // *** DO NOT LOCALIZE ***
  1881. Result := CF_LOGICALPERFORMEDDROPEFFECT;
  1882. end;
  1883. ////////////////////////////////////////////////////////////////////////////////
  1884. //
  1885. // TPasteSuccededClipboardFormat
  1886. //
  1887. ////////////////////////////////////////////////////////////////////////////////
  1888. var
  1889. CF_PASTESUCCEEDED: TClipFormat = 0;
  1890. function TPasteSuccededClipboardFormat.GetClipboardFormat: TClipFormat;
  1891. begin
  1892. if (CF_PASTESUCCEEDED = 0) then
  1893. CF_PASTESUCCEEDED := RegisterClipboardFormat(CFSTR_PASTESUCCEEDED);
  1894. Result := CF_PASTESUCCEEDED;
  1895. end;
  1896. ////////////////////////////////////////////////////////////////////////////////
  1897. //
  1898. // TInShellDragLoopClipboardFormat
  1899. //
  1900. ////////////////////////////////////////////////////////////////////////////////
  1901. var
  1902. CF_InDragLoop: TClipFormat = 0;
  1903. function TInShellDragLoopClipboardFormat.GetClipboardFormat: TClipFormat;
  1904. begin
  1905. if (CF_InDragLoop = 0) then
  1906. CF_InDragLoop := RegisterClipboardFormat(CFSTR_InDragLoop);
  1907. Result := CF_InDragLoop;
  1908. end;
  1909. ////////////////////////////////////////////////////////////////////////////////
  1910. //
  1911. // TTargetCLSIDClipboardFormat
  1912. //
  1913. ////////////////////////////////////////////////////////////////////////////////
  1914. procedure TTargetCLSIDClipboardFormat.Clear;
  1915. begin
  1916. FCLSID := GUID_NULL;
  1917. end;
  1918. var
  1919. CF_TargetCLSID: TClipFormat = 0;
  1920. function TTargetCLSIDClipboardFormat.GetClipboardFormat: TClipFormat;
  1921. begin
  1922. if (CF_TargetCLSID = 0) then
  1923. CF_TargetCLSID := RegisterClipboardFormat('TargetCLSID'); // *** DO NOT LOCALIZE ***
  1924. Result := CF_TargetCLSID;
  1925. end;
  1926. function TTargetCLSIDClipboardFormat.GetSize: integer;
  1927. begin
  1928. Result := SizeOf(TCLSID);
  1929. end;
  1930. function TTargetCLSIDClipboardFormat.HasData: boolean;
  1931. begin
  1932. Result := not IsEqualCLSID(FCLSID, GUID_NULL);
  1933. end;
  1934. function TTargetCLSIDClipboardFormat.ReadData(Value: pointer;
  1935. Size: integer): boolean;
  1936. begin
  1937. // Validate size.
  1938. Result := (Size = SizeOf(TCLSID));
  1939. if (Result) then
  1940. FCLSID := PCLSID(Value)^;
  1941. end;
  1942. function TTargetCLSIDClipboardFormat.WriteData(Value: pointer;
  1943. Size: integer): boolean;
  1944. begin
  1945. // Validate size.
  1946. Result := (Size = SizeOf(TCLSID));
  1947. if (Result) then
  1948. PCLSID(Value)^ := FCLSID;
  1949. end;
  1950. ////////////////////////////////////////////////////////////////////////////////
  1951. ////////////////////////////////////////////////////////////////////////////////
  1952. ////////////////////////////////////////////////////////////////////////////////
  1953. ////////////////////////////////////////////////////////////////////////////////
  1954. //
  1955. // TTextDataFormat
  1956. //
  1957. ////////////////////////////////////////////////////////////////////////////////
  1958. function TTextDataFormat.Assign(Source: TClipboardFormat): boolean;
  1959. begin
  1960. Result := True;
  1961. if (Source is TTextClipboardFormat) then
  1962. FText := TTextClipboardFormat(Source).Text
  1963. else if (Source is TFileContentsClipboardFormat) then
  1964. FText := TFileContentsClipboardFormat(Source).Data
  1965. else
  1966. Result := inherited Assign(Source);
  1967. end;
  1968. function TTextDataFormat.AssignTo(Dest: TClipboardFormat): boolean;
  1969. var
  1970. FGD: TFileGroupDescriptor;
  1971. FGDW: TFileGroupDescriptorW;
  1972. resourcestring
  1973. // Name of the text scrap file.
  1974. sTextScrap = 'Text scrap.txt';
  1975. begin
  1976. Result := True;
  1977. if (Dest is TTextClipboardFormat) then
  1978. TTextClipboardFormat(Dest).Text := FText
  1979. else if (Dest is TFileContentsClipboardFormat) then
  1980. TFileContentsClipboardFormat(Dest).Data := FText
  1981. else if (Dest is TFileGroupDescritorClipboardFormat) then
  1982. begin
  1983. FillChar(FGD, SizeOf(FGD), 0);
  1984. FGD.cItems := 1;
  1985. StrPLCopy(FGD.fgd[0].cFileName, sTextScrap, SizeOf(FGD.fgd[0].cFileName));
  1986. TFileGroupDescritorClipboardFormat(Dest).CopyFrom(@FGD);
  1987. end else
  1988. if (Dest is TFileGroupDescritorWClipboardFormat) then
  1989. begin
  1990. FillChar(FGDW, SizeOf(FGDW), 0);
  1991. FGDW.cItems := 1;
  1992. StringToWideChar(sTextScrap, PWideChar(@(FGDW.fgd[0].cFileName)), MAX_PATH);
  1993. TFileGroupDescritorWClipboardFormat(Dest).CopyFrom(@FGDW);
  1994. end else
  1995. Result := inherited AssignTo(Dest);
  1996. end;
  1997. procedure TTextDataFormat.Clear;
  1998. begin
  1999. Changing;
  2000. FText := '';
  2001. end;
  2002. procedure TTextDataFormat.SetText(const Value: string);
  2003. begin
  2004. Changing;
  2005. FText := Value;
  2006. end;
  2007. function TTextDataFormat.HasData: boolean;
  2008. begin
  2009. Result := (FText <> '');
  2010. end;
  2011. function TTextDataFormat.NeedsData: boolean;
  2012. begin
  2013. Result := (FText = '');
  2014. end;
  2015. ////////////////////////////////////////////////////////////////////////////////
  2016. //
  2017. // TDataStreamDataFormat
  2018. //
  2019. ////////////////////////////////////////////////////////////////////////////////
  2020. constructor TDataStreamDataFormat.Create(AOwner: TDragDropComponent);
  2021. begin
  2022. inherited Create(AOwner);
  2023. FStreams := TStreamList.Create;
  2024. FStreams.OnChanging := DoOnChanging;
  2025. end;
  2026. destructor TDataStreamDataFormat.Destroy;
  2027. begin
  2028. Clear;
  2029. FStreams.Free;
  2030. inherited Destroy;
  2031. end;
  2032. procedure TDataStreamDataFormat.Clear;
  2033. begin
  2034. Changing;
  2035. FStreams.Clear;
  2036. end;
  2037. function TDataStreamDataFormat.HasData: boolean;
  2038. begin
  2039. Result := (Streams.Count > 0);
  2040. end;
  2041. function TDataStreamDataFormat.NeedsData: boolean;
  2042. begin
  2043. Result := (Streams.Count = 0);
  2044. end;
  2045. ////////////////////////////////////////////////////////////////////////////////
  2046. //
  2047. // TFileDescriptorToFilenameStrings
  2048. //
  2049. ////////////////////////////////////////////////////////////////////////////////
  2050. // Used internally to convert between FileDescriptors and filenames on-demand.
  2051. ////////////////////////////////////////////////////////////////////////////////
  2052. type
  2053. TFileDescriptorToFilenameStrings = class(TStrings)
  2054. private
  2055. FFileDescriptors: TMemoryList;
  2056. protected
  2057. function Get(Index: Integer): string; override;
  2058. function GetCount: Integer; override;
  2059. public
  2060. constructor Create(AFileDescriptors: TMemoryList);
  2061. procedure Clear; override;
  2062. procedure Delete(Index: Integer); override;
  2063. procedure Insert(Index: Integer; const S: string); override;
  2064. procedure Assign(Source: TPersistent); override;
  2065. end;
  2066. constructor TFileDescriptorToFilenameStrings.Create(AFileDescriptors: TMemoryList);
  2067. begin
  2068. inherited Create;
  2069. FFileDescriptors := AFileDescriptors;
  2070. end;
  2071. function TFileDescriptorToFilenameStrings.Get(Index: Integer): string;
  2072. begin
  2073. Result := PFileDescriptor(FFileDescriptors[Index]).cFileName;
  2074. end;
  2075. function TFileDescriptorToFilenameStrings.GetCount: Integer;
  2076. begin
  2077. Result := FFileDescriptors.Count;
  2078. end;
  2079. procedure TFileDescriptorToFilenameStrings.Assign(Source: TPersistent);
  2080. var
  2081. i: integer;
  2082. begin
  2083. if Source is TStrings then
  2084. begin
  2085. BeginUpdate;
  2086. try
  2087. FFileDescriptors.Clear;
  2088. for i := 0 to TStrings(Source).Count-1 do
  2089. Add(TStrings(Source)[i]);
  2090. finally
  2091. EndUpdate;
  2092. end;
  2093. end else
  2094. inherited Assign(Source);
  2095. end;
  2096. procedure TFileDescriptorToFilenameStrings.Clear;
  2097. begin
  2098. FFileDescriptors.Clear;
  2099. end;
  2100. procedure TFileDescriptorToFilenameStrings.Delete(Index: Integer);
  2101. begin
  2102. FFileDescriptors.Delete(Index);
  2103. end;
  2104. procedure TFileDescriptorToFilenameStrings.Insert(Index: Integer; const S: string);
  2105. var
  2106. FD: PFileDescriptor;
  2107. begin
  2108. if (Index = FFileDescriptors.Count) then
  2109. begin
  2110. GetMem(FD, SizeOf(TFileDescriptor));
  2111. try
  2112. FillChar(FD^, SizeOf(TFileDescriptor), 0);
  2113. StrPLCopy(FD.cFileName, S, SizeOf(FD.cFileName));
  2114. FFileDescriptors.Add(FD);
  2115. except
  2116. FreeMem(FD);
  2117. raise;
  2118. end;
  2119. end;
  2120. end;
  2121. ////////////////////////////////////////////////////////////////////////////////
  2122. //
  2123. // TVirtualFileStreamDataFormat
  2124. //
  2125. ////////////////////////////////////////////////////////////////////////////////
  2126. constructor TVirtualFileStreamDataFormat.Create(AOwner: TDragDropComponent);
  2127. begin
  2128. inherited Create(AOwner);
  2129. FFileDescriptors := TMemoryList.Create;
  2130. FFileNames := TFileDescriptorToFilenameStrings.Create(FFileDescriptors);
  2131. // Add the "file group descriptor" and "file contents" clipboard formats to
  2132. // the data format's list of compatible formats.
  2133. // Note: This is normally done via TCustomDataFormat.RegisterCompatibleFormat,
  2134. // but since this data format and the clipboard format class are specialized
  2135. // to be used with each other, it is just as easy for us to add the formats
  2136. // manually.
  2137. FFileContentsClipboardFormat := TFileContentsStreamOnDemandClipboardFormat.Create;
  2138. CompatibleFormats.Add(FFileContentsClipboardFormat);
  2139. FFileGroupDescritorClipboardFormat := TFileGroupDescritorClipboardFormat.Create;
  2140. // Normaly TFileGroupDescritorClipboardFormat supports both HGlobal and
  2141. // IStream storage medium transfers, but for this demo we only use IStream.
  2142. // FFileGroupDescritorClipboardFormat.FormatEtc.tymed := TYMED_ISTREAM;
  2143. CompatibleFormats.Add(FFileGroupDescritorClipboardFormat);
  2144. end;
  2145. destructor TVirtualFileStreamDataFormat.Destroy;
  2146. begin
  2147. FFileDescriptors.Free;
  2148. FFileNames.Free;
  2149. inherited Destroy;
  2150. end;
  2151. procedure TVirtualFileStreamDataFormat.SetFileNames(const Value: TStrings);
  2152. begin
  2153. FFileNames.Assign(Value);
  2154. end;
  2155. {$IFOPT R+}
  2156. {$DEFINE R_PLUS}
  2157. {$RANGECHECKS OFF}
  2158. {$ENDIF}
  2159. function TVirtualFileStreamDataFormat.Assign(Source: TClipboardFormat): boolean;
  2160. var
  2161. i: integer;
  2162. FD: PFileDescriptor;
  2163. begin
  2164. Result := True;
  2165. (*
  2166. ** TFileContentsStreamOnDemandClipboardFormat
  2167. *)
  2168. if (Source is TFileContentsStreamOnDemandClipboardFormat) then
  2169. begin
  2170. FHasContents := TFileContentsStreamOnDemandClipboardFormat(Source).HasData;
  2171. end else
  2172. (*
  2173. ** TFileGroupDescritorClipboardFormat
  2174. *)
  2175. if (Source is TFileGroupDescritorClipboardFormat) then
  2176. begin
  2177. FFileDescriptors.Clear;
  2178. for i := 0 to TFileGroupDescritorClipboardFormat(Source).FileGroupDescriptor^.cItems-1 do
  2179. begin
  2180. GetMem(FD, SizeOf(TFileDescriptor));
  2181. try
  2182. Move(TFileGroupDescritorClipboardFormat(Source).FileGroupDescriptor^.fgd[i],
  2183. FD^, SizeOf(TFileDescriptor));
  2184. FFileDescriptors.Add(FD);
  2185. except
  2186. FreeMem(FD);
  2187. raise;
  2188. end;
  2189. end;
  2190. end else
  2191. (*
  2192. ** None of the above...
  2193. *)
  2194. Result := inherited Assign(Source);
  2195. end;
  2196. {$IFDEF R_PLUS}
  2197. {$RANGECHECKS ON}
  2198. {$UNDEF R_PLUS}
  2199. {$ENDIF}
  2200. {$IFOPT R+}
  2201. {$DEFINE R_PLUS}
  2202. {$RANGECHECKS OFF}
  2203. {$ENDIF}
  2204. function TVirtualFileStreamDataFormat.AssignTo(Dest: TClipboardFormat): boolean;
  2205. var
  2206. FGD: PFileGroupDescriptor;
  2207. i: integer;
  2208. begin
  2209. (*
  2210. ** TFileContentsStreamOnDemandClipboardFormat
  2211. *)
  2212. if (Dest is TFileContentsStreamOnDemandClipboardFormat) then
  2213. begin
  2214. // Let the clipboard format handle the transfer.
  2215. // No data is actually transferred, but TFileContentsStreamOnDemandClipboardFormat
  2216. // needs to set a flag when data is requested.
  2217. Result := Dest.Assign(Self);
  2218. end else
  2219. (*
  2220. ** TFileGroupDescritorClipboardFormat
  2221. *)
  2222. if (Dest is TFileGroupDescritorClipboardFormat) then
  2223. begin
  2224. if (FFileDescriptors.Count > 0) then
  2225. begin
  2226. GetMem(FGD, SizeOf(UINT) + FFileDescriptors.Count * SizeOf(TFileDescriptor));
  2227. try
  2228. FGD.cItems := FFileDescriptors.Count;
  2229. for i := 0 to FFileDescriptors.Count-1 do
  2230. Move(FFileDescriptors[i]^, FGD.fgd[i], SizeOf(TFileDescriptor));
  2231. TFileGroupDescritorClipboardFormat(Dest).CopyFrom(FGD);
  2232. finally
  2233. FreeMem(FGD);
  2234. end;
  2235. Result := True;
  2236. end else
  2237. Result := False;
  2238. end else
  2239. (*
  2240. ** None of the above...
  2241. *)
  2242. Result := inherited AssignTo(Dest);
  2243. end;
  2244. {$IFDEF R_PLUS}
  2245. {$RANGECHECKS ON}
  2246. {$UNDEF R_PLUS}
  2247. {$ENDIF}
  2248. procedure TVirtualFileStreamDataFormat.Clear;
  2249. begin
  2250. FFileDescriptors.Clear;
  2251. FHasContents := False;
  2252. end;
  2253. function TVirtualFileStreamDataFormat.HasData: boolean;
  2254. begin
  2255. Result := (FFileDescriptors.Count > 0) and
  2256. ((FHasContents) or Assigned(FFileContentsClipboardFormat.OnGetStream));
  2257. end;
  2258. function TVirtualFileStreamDataFormat.NeedsData: boolean;
  2259. begin
  2260. Result := (FFileDescriptors.Count = 0) or (not FHasContents);
  2261. end;
  2262. function TVirtualFileStreamDataFormat.GetOnGetStream: TOnGetStreamEvent;
  2263. begin
  2264. Result := FFileContentsClipboardFormat.OnGetStream;
  2265. end;
  2266. procedure TVirtualFileStreamDataFormat.SetOnGetStream(const Value: TOnGetStreamEvent);
  2267. begin
  2268. FFileContentsClipboardFormat.OnGetStream := Value;
  2269. end;
  2270. ////////////////////////////////////////////////////////////////////////////////
  2271. //
  2272. // TFeedbackDataFormat
  2273. //
  2274. ////////////////////////////////////////////////////////////////////////////////
  2275. function TFeedbackDataFormat.Assign(Source: TClipboardFormat): boolean;
  2276. begin
  2277. Result := True;
  2278. if (Source is TPreferredDropEffectClipboardFormat) then
  2279. FPreferredDropEffect := TPreferredDropEffectClipboardFormat(Source).Value
  2280. else if (Source is TPerformedDropEffectClipboardFormat) then
  2281. FPerformedDropEffect := TPerformedDropEffectClipboardFormat(Source).Value
  2282. else if (Source is TLogicalPerformedDropEffectClipboardFormat) then
  2283. FLogicalPerformedDropEffect := TLogicalPerformedDropEffectClipboardFormat(Source).Value
  2284. else if (Source is TPasteSuccededClipboardFormat) then
  2285. FPasteSucceded := TPasteSuccededClipboardFormat(Source).Value
  2286. else if (Source is TTargetCLSIDClipboardFormat) then
  2287. FTargetCLSID := TTargetCLSIDClipboardFormat(Source).CLSID
  2288. else if (Source is TInShellDragLoopClipboardFormat) then
  2289. begin
  2290. FInShellDragLoop := TInShellDragLoopClipboardFormat(Source).InShellDragLoop;
  2291. FGotInShellDragLoop := True;
  2292. end else
  2293. Result := inherited Assign(Source);
  2294. end;
  2295. function TFeedbackDataFormat.AssignTo(Dest: TClipboardFormat): boolean;
  2296. begin
  2297. Result := True;
  2298. if (Dest is TPreferredDropEffectClipboardFormat) then
  2299. TPreferredDropEffectClipboardFormat(Dest).Value := FPreferredDropEffect
  2300. else if (Dest is TPerformedDropEffectClipboardFormat) then
  2301. TPerformedDropEffectClipboardFormat(Dest).Value := FPerformedDropEffect
  2302. else if (Dest is TLogicalPerformedDropEffectClipboardFormat) then
  2303. TLogicalPerformedDropEffectClipboardFormat(Dest).Value := FLogicalPerformedDropEffect
  2304. else if (Dest is TPasteSuccededClipboardFormat) then
  2305. TPasteSuccededClipboardFormat(Dest).Value := FPasteSucceded
  2306. else if (Dest is TTargetCLSIDClipboardFormat) then
  2307. TTargetCLSIDClipboardFormat(Dest).CLSID := FTargetCLSID
  2308. else if (Dest is TInShellDragLoopClipboardFormat) then
  2309. TInShellDragLoopClipboardFormat(Dest).InShellDragLoop := FInShellDragLoop
  2310. else
  2311. Result := inherited AssignTo(Dest);
  2312. end;
  2313. procedure TFeedbackDataFormat.Clear;
  2314. begin
  2315. Changing;
  2316. FPreferredDropEffect := DROPEFFECT_NONE;
  2317. FPerformedDropEffect := DROPEFFECT_NONE;
  2318. FInShellDragLoop := False;
  2319. FGotInShellDragLoop := False;
  2320. end;
  2321. procedure TFeedbackDataFormat.SetInShellDragLoop(const Value: boolean);
  2322. begin
  2323. Changing;
  2324. FInShellDragLoop := Value;
  2325. end;
  2326. procedure TFeedbackDataFormat.SetPasteSucceded(const Value: longInt);
  2327. begin
  2328. Changing;
  2329. FPasteSucceded := Value;
  2330. end;
  2331. procedure TFeedbackDataFormat.SetPerformedDropEffect(
  2332. const Value: longInt);
  2333. begin
  2334. Changing;
  2335. FPerformedDropEffect := Value;
  2336. end;
  2337. procedure TFeedbackDataFormat.SetLogicalPerformedDropEffect(
  2338. const Value: longInt);
  2339. begin
  2340. Changing;
  2341. FLogicalPerformedDropEffect := Value;
  2342. end;
  2343. procedure TFeedbackDataFormat.SetPreferredDropEffect(
  2344. const Value: longInt);
  2345. begin
  2346. Changing;
  2347. FPreferredDropEffect := Value;
  2348. end;
  2349. procedure TFeedbackDataFormat.SetTargetCLSID(const Value: TCLSID);
  2350. begin
  2351. Changing;
  2352. FTargetCLSID := Value;
  2353. end;
  2354. function TFeedbackDataFormat.HasData: boolean;
  2355. begin
  2356. Result := (FPreferredDropEffect <> DROPEFFECT_NONE) or
  2357. (FPerformedDropEffect <> DROPEFFECT_NONE) or
  2358. (FPasteSucceded <> DROPEFFECT_NONE) or
  2359. (FGotInShellDragLoop);
  2360. end;
  2361. function TFeedbackDataFormat.NeedsData: boolean;
  2362. begin
  2363. Result := (FPreferredDropEffect = DROPEFFECT_NONE) or
  2364. (FPerformedDropEffect = DROPEFFECT_NONE) or
  2365. (FPasteSucceded = DROPEFFECT_NONE) or
  2366. (not FGotInShellDragLoop);
  2367. end;
  2368. ////////////////////////////////////////////////////////////////////////////////
  2369. //
  2370. // TGenericClipboardFormat
  2371. //
  2372. ////////////////////////////////////////////////////////////////////////////////
  2373. procedure TGenericClipboardFormat.SetClipboardFormatName(const Value: string);
  2374. begin
  2375. FFormat := Value;
  2376. if (FFormat <> '') then
  2377. ClipboardFormat := RegisterClipboardFormat(PChar(FFormat));
  2378. end;
  2379. function TGenericClipboardFormat.GetClipboardFormat: TClipFormat;
  2380. begin
  2381. if (FFormatEtc.cfFormat = 0) and (FFormat <> '') then
  2382. FFormatEtc.cfFormat := RegisterClipboardFormat(PChar(FFormat));
  2383. Result := FFormatEtc.cfFormat;
  2384. end;
  2385. function TGenericClipboardFormat.GetClipboardFormatName: string;
  2386. begin
  2387. Result := FFormat;
  2388. end;
  2389. function TGenericClipboardFormat.Assign(Source: TCustomDataFormat): boolean;
  2390. begin
  2391. if (Source is TGenericDataFormat) then
  2392. begin
  2393. Data := TGenericDataFormat(Source).Data;
  2394. Result := True;
  2395. end else
  2396. Result := inherited Assign(Source);
  2397. end;
  2398. function TGenericClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  2399. begin
  2400. if (Dest is TGenericDataFormat) then
  2401. begin
  2402. TGenericDataFormat(Dest).Data := Data;
  2403. Result := True;
  2404. end else
  2405. Result := inherited AssignTo(Dest);
  2406. end;
  2407. ////////////////////////////////////////////////////////////////////////////////
  2408. //
  2409. // TGenericDataFormat
  2410. //
  2411. ////////////////////////////////////////////////////////////////////////////////
  2412. procedure TGenericDataFormat.AddFormat(const AFormat: string);
  2413. var
  2414. ClipboardFormat: TGenericClipboardFormat;
  2415. begin
  2416. ClipboardFormat := TGenericClipboardFormat.Create;
  2417. ClipboardFormat.ClipboardFormatName := AFormat;
  2418. ClipboardFormat.DataDirections := [ddRead];
  2419. CompatibleFormats.Add(ClipboardFormat);
  2420. end;
  2421. procedure TGenericDataFormat.Clear;
  2422. begin
  2423. Changing;
  2424. FData := '';
  2425. end;
  2426. function TGenericDataFormat.HasData: boolean;
  2427. begin
  2428. Result := (FData <> '');
  2429. end;
  2430. function TGenericDataFormat.NeedsData: boolean;
  2431. begin
  2432. Result := (FData = '');
  2433. end;
  2434. procedure TGenericDataFormat.DoSetData(const Value: string);
  2435. begin
  2436. Changing;
  2437. FData := Value;
  2438. end;
  2439. procedure TGenericDataFormat.SetDataHere(const AData; ASize: integer);
  2440. begin
  2441. Changing;
  2442. SetLength(FData, ASize);
  2443. Move(AData, PChar(FData)^, ASize);
  2444. end;
  2445. function TGenericDataFormat.GetSize: integer;
  2446. begin
  2447. Result := length(FData);
  2448. end;
  2449. function TGenericDataFormat.GetDataHere(var AData; ASize: integer): integer;
  2450. begin
  2451. Result := Size;
  2452. if (ASize < Result) then
  2453. Result := ASize;
  2454. Move(PChar(FData)^, AData, Result);
  2455. end;
  2456. ////////////////////////////////////////////////////////////////////////////////
  2457. //
  2458. // Initialization/Finalization
  2459. //
  2460. ////////////////////////////////////////////////////////////////////////////////
  2461. initialization
  2462. // Data format registration
  2463. TTextDataFormat.RegisterDataFormat;
  2464. TDataStreamDataFormat.RegisterDataFormat;
  2465. TVirtualFileStreamDataFormat.RegisterDataFormat;
  2466. // Clipboard format registration
  2467. TTextDataFormat.RegisterCompatibleFormat(TTextClipboardFormat, 0, csSourceTarget, [ddRead]);
  2468. TTextDataFormat.RegisterCompatibleFormat(TFileContentsClipboardFormat, 1, csSourceTarget, [ddRead]);
  2469. TTextDataFormat.RegisterCompatibleFormat(TFileGroupDescritorClipboardFormat, 1, [csSource], [ddRead]);
  2470. TTextDataFormat.RegisterCompatibleFormat(TFileGroupDescritorWClipboardFormat, 1, [csSource], [ddRead]);
  2471. TFeedbackDataFormat.RegisterCompatibleFormat(TPreferredDropEffectClipboardFormat, 0, csSourceTarget, [ddRead]);
  2472. TFeedbackDataFormat.RegisterCompatibleFormat(TPerformedDropEffectClipboardFormat, 0, csSourceTarget, [ddWrite]);
  2473. TFeedbackDataFormat.RegisterCompatibleFormat(TPasteSuccededClipboardFormat, 0, csSourceTarget, [ddWrite]);
  2474. TFeedbackDataFormat.RegisterCompatibleFormat(TInShellDragLoopClipboardFormat, 0, csSourceTarget, [ddRead]);
  2475. TFeedbackDataFormat.RegisterCompatibleFormat(TTargetCLSIDClipboardFormat, 0, csSourceTarget, [ddWrite]);
  2476. TFeedbackDataFormat.RegisterCompatibleFormat(TLogicalPerformedDropEffectClipboardFormat, 0, csSourceTarget, [ddWrite]);
  2477. TDataStreamDataFormat.RegisterCompatibleFormat(TFileContentsStreamClipboardFormat, 0, [csTarget], [ddRead]);
  2478. finalization
  2479. TTextDataFormat.UnregisterDataFormat;
  2480. TDataStreamDataFormat.UnregisterDataFormat;
  2481. TFeedbackDataFormat.UnregisterDataFormat;
  2482. TVirtualFileStreamDataFormat.UnregisterDataFormat;
  2483. TTextClipboardFormat.UnregisterClipboardFormat;
  2484. TFileGroupDescritorClipboardFormat.UnregisterClipboardFormat;
  2485. TFileGroupDescritorWClipboardFormat.UnregisterClipboardFormat;
  2486. TFileContentsClipboardFormat.UnregisterClipboardFormat;
  2487. TFileContentsStreamClipboardFormat.UnregisterClipboardFormat;
  2488. TPreferredDropEffectClipboardFormat.UnregisterClipboardFormat;
  2489. TPerformedDropEffectClipboardFormat.UnregisterClipboardFormat;
  2490. TPasteSuccededClipboardFormat.UnregisterClipboardFormat;
  2491. TInShellDragLoopClipboardFormat.UnregisterClipboardFormat;
  2492. TTargetCLSIDClipboardFormat.UnregisterClipboardFormat;
  2493. TLogicalPerformedDropEffectClipboardFormat.UnregisterClipboardFormat;
  2494. end.