DragDropText.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. unit DragDropText;
  2. // -----------------------------------------------------------------------------
  3. // Project: Drag and Drop Component Suite.
  4. // Module: DragDropText
  5. // Description: Implements Dragging and Dropping of different text formats.
  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. DropTarget,
  16. DropSource,
  17. DragDropFormats,
  18. ActiveX,
  19. Windows,
  20. Classes;
  21. type
  22. ////////////////////////////////////////////////////////////////////////////////
  23. //
  24. // TRichTextClipboardFormat
  25. //
  26. ////////////////////////////////////////////////////////////////////////////////
  27. TRichTextClipboardFormat = class(TCustomTextClipboardFormat)
  28. public
  29. function GetClipboardFormat: TClipFormat; override;
  30. function HasData: boolean; override;
  31. function Assign(Source: TCustomDataFormat): boolean; override;
  32. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  33. property Text;
  34. end;
  35. ////////////////////////////////////////////////////////////////////////////////
  36. //
  37. // TUnicodeTextClipboardFormat
  38. //
  39. ////////////////////////////////////////////////////////////////////////////////
  40. TUnicodeTextClipboardFormat = class(TCustomWideTextClipboardFormat)
  41. public
  42. function GetClipboardFormat: TClipFormat; override;
  43. function Assign(Source: TCustomDataFormat): boolean; override;
  44. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  45. property Text;
  46. end;
  47. ////////////////////////////////////////////////////////////////////////////////
  48. //
  49. // TOEMTextClipboardFormat
  50. //
  51. ////////////////////////////////////////////////////////////////////////////////
  52. TOEMTextClipboardFormat = class(TCustomTextClipboardFormat)
  53. public
  54. function GetClipboardFormat: TClipFormat; override;
  55. function Assign(Source: TCustomDataFormat): boolean; override;
  56. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  57. property Text;
  58. end;
  59. ////////////////////////////////////////////////////////////////////////////////
  60. //
  61. // TCSVClipboardFormat
  62. //
  63. ////////////////////////////////////////////////////////////////////////////////
  64. TCSVClipboardFormat = class(TCustomStringListClipboardFormat)
  65. public
  66. function GetClipboardFormat: TClipFormat; override;
  67. function Assign(Source: TCustomDataFormat): boolean; override;
  68. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  69. property Lines;
  70. end;
  71. ////////////////////////////////////////////////////////////////////////////////
  72. //
  73. // TLocaleClipboardFormat
  74. //
  75. ////////////////////////////////////////////////////////////////////////////////
  76. TLocaleClipboardFormat = class(TCustomDWORDClipboardFormat)
  77. public
  78. function GetClipboardFormat: TClipFormat; override;
  79. function HasData: boolean; override;
  80. function Assign(Source: TCustomDataFormat): boolean; override;
  81. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  82. property Locale: DWORD read GetValueDWORD;
  83. end;
  84. ////////////////////////////////////////////////////////////////////////////////
  85. //
  86. // TDropTextTarget
  87. //
  88. ////////////////////////////////////////////////////////////////////////////////
  89. TDropTextTarget = class(TCustomDropMultiTarget)
  90. private
  91. FTextFormat : TTextDataFormat;
  92. protected
  93. function GetText: string;
  94. public
  95. constructor Create(AOwner: TComponent); override;
  96. destructor Destroy; override;
  97. property Text: string read GetText;
  98. end;
  99. ////////////////////////////////////////////////////////////////////////////////
  100. //
  101. // TDropTextSource
  102. //
  103. ////////////////////////////////////////////////////////////////////////////////
  104. TDropTextSource = class(TCustomDropMultiSource)
  105. private
  106. FTextFormat : TTextDataFormat;
  107. protected
  108. function GetText: string;
  109. procedure SetText(const Value: string);
  110. public
  111. constructor Create(aOwner: TComponent); override;
  112. destructor Destroy; override;
  113. published
  114. property Text: string read GetText write SetText;
  115. end;
  116. ////////////////////////////////////////////////////////////////////////////////
  117. //
  118. // Component registration
  119. //
  120. ////////////////////////////////////////////////////////////////////////////////
  121. procedure Register;
  122. ////////////////////////////////////////////////////////////////////////////////
  123. //
  124. // Misc.
  125. //
  126. ////////////////////////////////////////////////////////////////////////////////
  127. function IsRTF(const s: string): boolean;
  128. function MakeRTF(const s: string): string;
  129. ////////////////////////////////////////////////////////////////////////////////
  130. ////////////////////////////////////////////////////////////////////////////////
  131. //
  132. // IMPLEMENTATION
  133. //
  134. ////////////////////////////////////////////////////////////////////////////////
  135. ////////////////////////////////////////////////////////////////////////////////
  136. implementation
  137. uses
  138. SysUtils;
  139. ////////////////////////////////////////////////////////////////////////////////
  140. //
  141. // Component registration
  142. //
  143. ////////////////////////////////////////////////////////////////////////////////
  144. procedure Register;
  145. begin
  146. RegisterComponents(DragDropComponentPalettePage, [TDropTextTarget,
  147. TDropTextSource]);
  148. end;
  149. ////////////////////////////////////////////////////////////////////////////////
  150. //
  151. // Utilities
  152. //
  153. ////////////////////////////////////////////////////////////////////////////////
  154. function IsRTF(const s: string): boolean;
  155. begin
  156. // This probably isn't a valid test, but it will have to do until I have
  157. // time to research the RTF specifications.
  158. { TODO -oanme -cImprovement : Need a solid test for RTF format. }
  159. Result := (AnsiStrLIComp(PChar(s), '{\rtf', 5) = 0);
  160. end;
  161. { TODO -oanme -cImprovement : Needs RTF to text conversion. Maybe ITextDocument can be used. }
  162. function MakeRTF(const s: string): string;
  163. begin
  164. { TODO -oanme -cImprovement : Needs to escape \ in text to RTF conversion. }
  165. { TODO -oanme -cImprovement : Needs better text to RTF conversion. }
  166. if (not IsRTF(s)) then
  167. Result := '{\rtf1\ansi ' + s + '}'
  168. else
  169. Result := s;
  170. end;
  171. ////////////////////////////////////////////////////////////////////////////////
  172. //
  173. // TRichTextClipboardFormat
  174. //
  175. ////////////////////////////////////////////////////////////////////////////////
  176. var
  177. CF_RTF: TClipFormat = 0;
  178. function TRichTextClipboardFormat.GetClipboardFormat: TClipFormat;
  179. begin
  180. // Note: The string 'Rich Text Format', is also defined in the RichEdit
  181. // unit as CF_RTF
  182. if (CF_RTF = 0) then
  183. CF_RTF := RegisterClipboardFormat('Rich Text Format'); // *** DO NOT LOCALIZE ***
  184. Result := CF_RTF;
  185. end;
  186. function TRichTextClipboardFormat.HasData: boolean;
  187. begin
  188. Result := inherited HasData and IsRTF(Text);
  189. end;
  190. function TRichTextClipboardFormat.Assign(Source: TCustomDataFormat): boolean;
  191. begin
  192. if (Source is TTextDataFormat) then
  193. begin
  194. Text := MakeRTF(TTextDataFormat(Source).Text);
  195. Result := True;
  196. end else
  197. Result := inherited Assign(Source);
  198. end;
  199. function TRichTextClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  200. begin
  201. if (Dest is TTextDataFormat) then
  202. begin
  203. TTextDataFormat(Dest).Text := Text;
  204. Result := True;
  205. end else
  206. Result := inherited AssignTo(Dest);
  207. end;
  208. ////////////////////////////////////////////////////////////////////////////////
  209. //
  210. // TUnicodeTextClipboardFormat
  211. //
  212. ////////////////////////////////////////////////////////////////////////////////
  213. function TUnicodeTextClipboardFormat.GetClipboardFormat: TClipFormat;
  214. begin
  215. Result := CF_UNICODETEXT;
  216. end;
  217. function TUnicodeTextClipboardFormat.Assign(Source: TCustomDataFormat): boolean;
  218. begin
  219. if (Source is TTextDataFormat) then
  220. begin
  221. Text := TTextDataFormat(Source).Text;
  222. Result := True;
  223. end else
  224. Result := inherited Assign(Source);
  225. end;
  226. function TUnicodeTextClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  227. begin
  228. if (Dest is TTextDataFormat) then
  229. begin
  230. TTextDataFormat(Dest).Text := Text;
  231. Result := True;
  232. end else
  233. Result := inherited AssignTo(Dest);
  234. end;
  235. ////////////////////////////////////////////////////////////////////////////////
  236. //
  237. // TOEMTextClipboardFormat
  238. //
  239. ////////////////////////////////////////////////////////////////////////////////
  240. function TOEMTextClipboardFormat.GetClipboardFormat: TClipFormat;
  241. begin
  242. Result := CF_OEMTEXT;
  243. end;
  244. function TOEMTextClipboardFormat.Assign(Source: TCustomDataFormat): boolean;
  245. var
  246. OEMText : string;
  247. begin
  248. if (Source is TTextDataFormat) then
  249. begin
  250. // First convert ANSI string to OEM string...
  251. SetLength(OEMText, Length(TTextDataFormat(Source).Text));
  252. CharToOemBuff(PChar(TTextDataFormat(Source).Text), PChar(OEMText),
  253. Length(TTextDataFormat(Source).Text));
  254. // ...then assign OEM string
  255. Text := OEMText;
  256. Result := True;
  257. end else
  258. Result := inherited Assign(Source);
  259. end;
  260. function TOEMTextClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  261. var
  262. AnsiText : string;
  263. begin
  264. if (Dest is TTextDataFormat) then
  265. begin
  266. // First convert OEM string to ANSI string...
  267. SetLength(AnsiText, Length(Text));
  268. OemToCharBuff(PChar(Text), PChar(AnsiText), Length(Text));
  269. // ...then assign ANSI string
  270. TTextDataFormat(Dest).Text := AnsiText;
  271. Result := True;
  272. end else
  273. Result := inherited AssignTo(Dest);
  274. end;
  275. ////////////////////////////////////////////////////////////////////////////////
  276. //
  277. // TCSVClipboardFormat
  278. //
  279. ////////////////////////////////////////////////////////////////////////////////
  280. var
  281. CF_CSV: TClipFormat = 0;
  282. function TCSVClipboardFormat.GetClipboardFormat: TClipFormat;
  283. begin
  284. if (CF_CSV = 0) then
  285. CF_CSV := RegisterClipboardFormat('CSV'); // *** DO NOT LOCALIZE ***
  286. Result := CF_CSV;
  287. end;
  288. function TCSVClipboardFormat.Assign(Source: TCustomDataFormat): boolean;
  289. begin
  290. if (Source is TTextDataFormat) then
  291. begin
  292. Lines.Text := TTextDataFormat(Source).Text;
  293. Result := True;
  294. end else
  295. Result := inherited AssignTo(Source);
  296. end;
  297. function TCSVClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  298. begin
  299. if (Dest is TTextDataFormat) then
  300. begin
  301. TTextDataFormat(Dest).Text := Lines.Text;
  302. Result := True;
  303. end else
  304. Result := inherited AssignTo(Dest);
  305. end;
  306. ////////////////////////////////////////////////////////////////////////////////
  307. //
  308. // TLocaleClipboardFormat
  309. //
  310. ////////////////////////////////////////////////////////////////////////////////
  311. function TLocaleClipboardFormat.GetClipboardFormat: TClipFormat;
  312. begin
  313. Result := CF_LOCALE;
  314. end;
  315. function TLocaleClipboardFormat.HasData: boolean;
  316. begin
  317. Result := (Locale <> 0);
  318. end;
  319. function TLocaleClipboardFormat.Assign(Source: TCustomDataFormat): boolean;
  320. begin
  321. // So far we have no one to play with...
  322. Result := inherited Assign(Source);
  323. end;
  324. function TLocaleClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  325. begin
  326. // So far we have no one to play with...
  327. Result := inherited AssignTo(Dest);
  328. end;
  329. ////////////////////////////////////////////////////////////////////////////////
  330. //
  331. // TDropTextTarget
  332. //
  333. ////////////////////////////////////////////////////////////////////////////////
  334. constructor TDropTextTarget.Create(AOwner: TComponent);
  335. begin
  336. inherited Create(AOwner);
  337. FTextFormat := TTextDataFormat.Create(Self);
  338. end;
  339. destructor TDropTextTarget.Destroy;
  340. begin
  341. FTextFormat.Free;
  342. inherited Destroy;
  343. end;
  344. function TDropTextTarget.GetText: string;
  345. begin
  346. Result := FTextFormat.Text;
  347. end;
  348. ////////////////////////////////////////////////////////////////////////////////
  349. //
  350. // TDropTextSource
  351. //
  352. ////////////////////////////////////////////////////////////////////////////////
  353. constructor TDropTextSource.Create(aOwner: TComponent);
  354. begin
  355. inherited Create(aOwner);
  356. FTextFormat := TTextDataFormat.Create(Self);
  357. end;
  358. destructor TDropTextSource.Destroy;
  359. begin
  360. FTextFormat.Free;
  361. inherited Destroy;
  362. end;
  363. function TDropTextSource.GetText: string;
  364. begin
  365. Result := FTextFormat.Text;
  366. end;
  367. procedure TDropTextSource.SetText(const Value: string);
  368. begin
  369. FTextFormat.Text := Value;
  370. end;
  371. ////////////////////////////////////////////////////////////////////////////////
  372. //
  373. // Initialization/Finalization
  374. //
  375. ////////////////////////////////////////////////////////////////////////////////
  376. initialization
  377. // Clipboard format registration
  378. TTextDataFormat.RegisterCompatibleFormat(TUnicodeTextClipboardFormat, 1, csSourceTarget, [ddRead]);
  379. TTextDataFormat.RegisterCompatibleFormat(TRichTextClipboardFormat, 2, csSourceTarget, [ddRead]);
  380. TTextDataFormat.RegisterCompatibleFormat(TOEMTextClipboardFormat, 2, csSourceTarget, [ddRead]);
  381. TTextDataFormat.RegisterCompatibleFormat(TCSVClipboardFormat, 3, csSourceTarget, [ddRead]);
  382. finalization
  383. // Clipboard format unregistration
  384. TUnicodeTextClipboardFormat.UnregisterClipboardFormat;
  385. TRichTextClipboardFormat.UnregisterClipboardFormat;
  386. TOEMTextClipboardFormat.UnregisterClipboardFormat;
  387. TCSVClipboardFormat.UnregisterClipboardFormat;
  388. end.