DragDropGraphics.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. unit DragDropGraphics;
  2. // -----------------------------------------------------------------------------
  3. // Project: Drag and Drop Component Suite.
  4. // Module: DragDropGraphics
  5. // Description: Implements Dragging and Dropping of graphic data.
  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. ActiveX,
  18. Windows,
  19. Graphics,
  20. Classes;
  21. {$include DragDrop.inc}
  22. type
  23. ////////////////////////////////////////////////////////////////////////////////
  24. //
  25. // TGDIClipboardFormat
  26. //
  27. ////////////////////////////////////////////////////////////////////////////////
  28. // Base class for GDI clipboard formats (TYMED_GDI).
  29. ////////////////////////////////////////////////////////////////////////////////
  30. TGDIClipboardFormat = class(TClipboardFormat)
  31. public
  32. constructor Create; override;
  33. end;
  34. ////////////////////////////////////////////////////////////////////////////////
  35. //
  36. // TPaletteClipboardFormat
  37. //
  38. ////////////////////////////////////////////////////////////////////////////////
  39. // Only used internally by TBitmapClipboardFormat - Not registered
  40. ////////////////////////////////////////////////////////////////////////////////
  41. TPaletteClipboardFormat = class(TGDIClipboardFormat)
  42. private
  43. FPalette : hPalette;
  44. public
  45. function GetClipboardFormat: TClipFormat; override;
  46. function DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean; override;
  47. function DoSetData(const FormatEtcIn: TFormatEtc;
  48. var Medium: TStgMedium): boolean; override;
  49. procedure Clear; override;
  50. property Palette: hPalette read FPalette write FPalette;
  51. end;
  52. ////////////////////////////////////////////////////////////////////////////////
  53. //
  54. // TCustomBitmapClipboardFormat
  55. //
  56. ////////////////////////////////////////////////////////////////////////////////
  57. TCustomBitmapClipboardFormat = class(TGDIClipboardFormat)
  58. private
  59. FBitmap : TBitmap;
  60. protected
  61. constructor CreateFormat(Atymed: Longint); override;
  62. public
  63. destructor Destroy; override;
  64. procedure Clear; override;
  65. property Bitmap: TBitmap read FBitmap;
  66. end;
  67. ////////////////////////////////////////////////////////////////////////////////
  68. //
  69. // TBitmapClipboardFormat
  70. //
  71. ////////////////////////////////////////////////////////////////////////////////
  72. TBitmapClipboardFormat = class(TCustomBitmapClipboardFormat)
  73. protected
  74. function DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean; override;
  75. function DoSetData(const FormatEtcIn: TFormatEtc;
  76. var AMedium: TStgMedium): boolean; override;
  77. public
  78. function GetClipboardFormat: TClipFormat; override;
  79. end;
  80. ////////////////////////////////////////////////////////////////////////////////
  81. //
  82. // TDIBClipboardFormat
  83. //
  84. ////////////////////////////////////////////////////////////////////////////////
  85. TDIBClipboardFormat = class(TCustomBitmapClipboardFormat)
  86. private
  87. protected
  88. function DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean; override;
  89. function DoSetData(const FormatEtcIn: TFormatEtc;
  90. var AMedium: TStgMedium): boolean; override;
  91. public
  92. constructor Create; override;
  93. function GetClipboardFormat: TClipFormat; override;
  94. end;
  95. ////////////////////////////////////////////////////////////////////////////////
  96. //
  97. // TCustomMetaFileClipboardFormat
  98. //
  99. ////////////////////////////////////////////////////////////////////////////////
  100. TCustomMetaFileClipboardFormat = class(TClipboardFormat)
  101. private
  102. FMetaFile : TMetaFile;
  103. protected
  104. public
  105. constructor Create; override;
  106. destructor Destroy; override;
  107. procedure Clear; override;
  108. property MetaFile: TMetaFile read FMetaFile;
  109. end;
  110. ////////////////////////////////////////////////////////////////////////////////
  111. //
  112. // TMetaFileClipboardFormat
  113. //
  114. ////////////////////////////////////////////////////////////////////////////////
  115. TMetaFileClipboardFormat = class(TCustomMetaFileClipboardFormat)
  116. private
  117. protected
  118. function DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean; override;
  119. public
  120. function GetClipboardFormat: TClipFormat; override;
  121. end;
  122. ////////////////////////////////////////////////////////////////////////////////
  123. //
  124. // TEnhMetaFileClipboardFormat
  125. //
  126. ////////////////////////////////////////////////////////////////////////////////
  127. TEnhMetaFileClipboardFormat = class(TCustomMetaFileClipboardFormat)
  128. private
  129. protected
  130. function DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean; override;
  131. public
  132. function GetClipboardFormat: TClipFormat; override;
  133. end;
  134. ////////////////////////////////////////////////////////////////////////////////
  135. //
  136. // TBitmapDataFormat
  137. //
  138. ////////////////////////////////////////////////////////////////////////////////
  139. TBitmapDataFormat = class(TCustomDataFormat)
  140. private
  141. FBitmap : TBitmap;
  142. protected
  143. public
  144. constructor Create(AOwner: TDragDropComponent); override;
  145. destructor Destroy; override;
  146. function Assign(Source: TClipboardFormat): boolean; override;
  147. function AssignTo(Dest: TClipboardFormat): boolean; override;
  148. procedure Clear; override;
  149. function HasData: boolean; override;
  150. function NeedsData: boolean; override;
  151. property Bitmap: TBitmap read FBitmap;
  152. end;
  153. ////////////////////////////////////////////////////////////////////////////////
  154. //
  155. // TMetaFileDataFormat
  156. //
  157. ////////////////////////////////////////////////////////////////////////////////
  158. TMetaFileDataFormat = class(TCustomDataFormat)
  159. private
  160. FMetaFile : TMetaFile;
  161. protected
  162. public
  163. constructor Create(AOwner: TDragDropComponent); override;
  164. destructor Destroy; override;
  165. function Assign(Source: TClipboardFormat): boolean; override;
  166. procedure Clear; override;
  167. function HasData: boolean; override;
  168. function NeedsData: boolean; override;
  169. property MetaFile: TMetaFile read FMetaFile;
  170. end;
  171. ////////////////////////////////////////////////////////////////////////////////
  172. //
  173. // TDropBMPTarget
  174. //
  175. ////////////////////////////////////////////////////////////////////////////////
  176. TDropBMPTarget = class(TCustomDropMultiTarget)
  177. private
  178. FBitmapFormat : TBitmapDataFormat;
  179. protected
  180. function GetBitmap: TBitmap;
  181. public
  182. constructor Create(AOwner: TComponent); override;
  183. destructor Destroy; override;
  184. property Bitmap: TBitmap read GetBitmap;
  185. end;
  186. ////////////////////////////////////////////////////////////////////////////////
  187. //
  188. // TDropBMPSource
  189. //
  190. ////////////////////////////////////////////////////////////////////////////////
  191. TDropBMPSource = class(TCustomDropMultiSource)
  192. private
  193. FBitmapFormat : TBitmapDataFormat;
  194. protected
  195. procedure SetBitmap(const Value: TBitmap);
  196. function GetBitmap: TBitmap;
  197. public
  198. constructor Create(AOwner: TComponent); override;
  199. destructor Destroy; override;
  200. published
  201. property Bitmap: TBitmap read GetBitmap write SetBitmap;
  202. end;
  203. ////////////////////////////////////////////////////////////////////////////////
  204. //
  205. // TDropMetaFileTarget
  206. //
  207. ////////////////////////////////////////////////////////////////////////////////
  208. TDropMetaFileTarget = class(TCustomDropMultiTarget)
  209. private
  210. FMetaFileFormat : TMetaFileDataFormat;
  211. protected
  212. function GetMetaFile: TMetaFile;
  213. public
  214. constructor Create(AOwner: TComponent); override;
  215. destructor Destroy; override;
  216. property MetaFile: TMetaFile read GetMetaFile;
  217. end;
  218. ////////////////////////////////////////////////////////////////////////////////
  219. //
  220. // TDropImageTarget
  221. //
  222. ////////////////////////////////////////////////////////////////////////////////
  223. TDropImageTarget = class(TCustomDropMultiTarget)
  224. private
  225. FMetaFileFormat : TMetaFileDataFormat;
  226. FBitmapFormat : TBitmapDataFormat;
  227. FPicture : TPicture;
  228. protected
  229. function DoGetData: boolean; override;
  230. procedure ClearData; override;
  231. public
  232. constructor Create(AOwner: TComponent); override;
  233. destructor Destroy; override;
  234. property Picture: TPicture read FPicture;
  235. end;
  236. ////////////////////////////////////////////////////////////////////////////////
  237. //
  238. // Component registration
  239. //
  240. ////////////////////////////////////////////////////////////////////////////////
  241. procedure Register;
  242. ////////////////////////////////////////////////////////////////////////////////
  243. //
  244. // Misc.
  245. //
  246. ////////////////////////////////////////////////////////////////////////////////
  247. procedure CopyDIBToBitmap(Bitmap: TBitmap; BitmapInfo: PBitmapInfo; DIBSize: integer);
  248. function GetHGlobalDIBFromBitmap(Bitmap: TBitmap): HGlobal;
  249. ////////////////////////////////////////////////////////////////////////////////
  250. ////////////////////////////////////////////////////////////////////////////////
  251. //
  252. // IMPLEMENTATION
  253. //
  254. ////////////////////////////////////////////////////////////////////////////////
  255. ////////////////////////////////////////////////////////////////////////////////
  256. implementation
  257. uses
  258. SysUtils;
  259. ////////////////////////////////////////////////////////////////////////////////
  260. //
  261. // Component registration
  262. //
  263. ////////////////////////////////////////////////////////////////////////////////
  264. procedure Register;
  265. begin
  266. RegisterComponents(DragDropComponentPalettePage, [TDropBMPTarget,
  267. TDropBMPSource, TDropMetaFileTarget, TDropImageTarget]);
  268. end;
  269. ////////////////////////////////////////////////////////////////////////////////
  270. //
  271. // Misc.
  272. //
  273. ////////////////////////////////////////////////////////////////////////////////
  274. procedure CopyDIBToBitmap(Bitmap: TBitmap; BitmapInfo: PBitmapInfo; DIBSize: integer);
  275. var
  276. BitmapFileHeader : TBitmapFileHeader;
  277. FileSize : integer;
  278. InfoSize : integer;
  279. Stream : TMemoryStream;
  280. begin
  281. // Write DIB to a stream in the BMP file format
  282. Stream := TMemoryStream.Create;
  283. try
  284. FileSize := sizeof(TBitmapFileHeader) + DIBSize;
  285. InfoSize := sizeof(TBitmapInfoHeader);
  286. if (BitmapInfo^.bmiHeader.biBitCount > 8) then
  287. begin
  288. if ((BitmapInfo^.bmiHeader.biCompression and BI_BITFIELDS) <> 0) then
  289. Inc(InfoSize, 12);
  290. end else
  291. Inc(InfoSize, sizeof(TRGBQuad) * (1 shl BitmapInfo^.bmiHeader.biBitCount));
  292. Stream.SetSize(FileSize);
  293. // Initialize file header
  294. FillChar(BitmapFileHeader, sizeof(TBitmapFileHeader), 0);
  295. with BitmapFileHeader do
  296. begin
  297. bfType := $4D42; // 'BM' = Windows BMP signature
  298. bfSize := FileSize; // File size (not needed)
  299. bfOffBits := sizeof(TBitmapFileHeader) + InfoSize; // Offset of pixel data
  300. end;
  301. // Save file header
  302. Stream.Write(BitmapFileHeader, sizeof(TBitmapFileHeader));
  303. // Save TBitmapInfo structure and pixel data
  304. Stream.Write(BitmapInfo^, DIBSize);
  305. // Rewind and load bitmap from stream
  306. Stream.Position := 0;
  307. Bitmap.LoadFromStream(Stream);
  308. finally
  309. Stream.Free;
  310. end;
  311. end;
  312. function GetHGlobalDIBFromBitmap(Bitmap: TBitmap): HGlobal;
  313. var
  314. Stream : TMemoryStream;
  315. DIB : pointer;
  316. DIBSize : integer;
  317. begin
  318. Stream := TMemoryStream.Create;
  319. try
  320. // Write bitmap to a stream and extract the DIB data from it.
  321. Bitmap.SaveToStream(Stream);
  322. // Calculate size of DIB block.
  323. DIBSize := Stream.Size - SizeOf(TBitmapFileHeader);
  324. // Allocate memory for DIB data.
  325. Result := GlobalAlloc(GMEM_MOVEABLE or GMEM_SHARE, DIBSize);
  326. if (Result = 0) then
  327. exit;
  328. DIB := GlobalLock(Result);
  329. if DIB = nil then
  330. begin
  331. GlobalFree(Result);
  332. Result := 0;
  333. end else
  334. begin
  335. // Skip BMP file header.
  336. Stream.Seek(SizeOf(TBitmapFileHeader), soFromBeginning);
  337. // Transfer data from stream to global memory.
  338. if (Stream.Read(DIB^, DIBSize) <> DIBSize) then
  339. begin
  340. GlobalUnlock(Result);
  341. GlobalFree(Result);
  342. Result := 0;
  343. end else
  344. GlobalUnlock(Result);
  345. end;
  346. finally
  347. Stream.free;
  348. end;
  349. end;
  350. ////////////////////////////////////////////////////////////////////////////////
  351. //
  352. // TGDIClipboardFormat
  353. //
  354. ////////////////////////////////////////////////////////////////////////////////
  355. constructor TGDIClipboardFormat.Create;
  356. begin
  357. CreateFormat(TYMED_GDI);
  358. end;
  359. ////////////////////////////////////////////////////////////////////////////////
  360. //
  361. // TPaletteClipboardFormat
  362. //
  363. ////////////////////////////////////////////////////////////////////////////////
  364. function TPaletteClipboardFormat.GetClipboardFormat: TClipFormat;
  365. begin
  366. Result := CF_PALETTE;
  367. end;
  368. procedure TPaletteClipboardFormat.Clear;
  369. begin
  370. if (FPalette <> 0) then
  371. begin
  372. DeleteObject(FPalette);
  373. FPalette := 0;
  374. end;
  375. end;
  376. function TPaletteClipboardFormat.DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean;
  377. begin
  378. if (AMedium.hBitmap <> 0) then
  379. begin
  380. FPalette := CopyPalette(AMedium.hBitmap);
  381. Result := (FPalette <> 0);
  382. end else
  383. Result := False;
  384. end;
  385. function TPaletteClipboardFormat.DoSetData(const FormatEtcIn: TFormatEtc;
  386. var Medium: TStgMedium): boolean;
  387. begin
  388. Result := False;
  389. try
  390. Medium.hBitmap := CopyPalette(FPalette);
  391. except
  392. exit;
  393. end;
  394. if (Medium.hBitmap <> 0) then
  395. begin
  396. Medium.tymed := TYMED_GDI;
  397. result := True;
  398. end;
  399. end;
  400. ////////////////////////////////////////////////////////////////////////////////
  401. //
  402. // TBitmapClipboardFormat
  403. //
  404. ////////////////////////////////////////////////////////////////////////////////
  405. constructor TCustomBitmapClipboardFormat.CreateFormat(Atymed: Longint);
  406. begin
  407. inherited CreateFormat(Atymed);
  408. FBitmap := Graphics.TBitmap.Create;
  409. end;
  410. destructor TCustomBitmapClipboardFormat.Destroy;
  411. begin
  412. if (FBitmap <> nil) then
  413. FBitmap.Free;
  414. inherited Destroy;
  415. end;
  416. procedure TCustomBitmapClipboardFormat.Clear;
  417. begin
  418. FBitmap.Handle := 0;
  419. end;
  420. ////////////////////////////////////////////////////////////////////////////////
  421. //
  422. // TBitmapClipboardFormat
  423. //
  424. ////////////////////////////////////////////////////////////////////////////////
  425. function TBitmapClipboardFormat.GetClipboardFormat: TClipFormat;
  426. begin
  427. Result := CF_BITMAP;
  428. end;
  429. function TBitmapClipboardFormat.DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean;
  430. var
  431. Palette : TPaletteClipboardFormat;
  432. begin
  433. Result := False;
  434. if (AMedium.hBitmap = 0) then
  435. exit;
  436. Palette := TPaletteClipboardFormat.Create;
  437. try
  438. // Attempt to get palette from source. However in case the bitmap is in a
  439. // format which doesn't use palettes, there might not be one available.
  440. // The CF_BITMAP/CF_PALETTE documentation doesn't mention if CF_BITMAP must
  441. // always be accompanied with a CF_PALETTE.
  442. Palette.GetData(ADataObject);
  443. // Let TBitmap do the work for us.
  444. FBitmap.LoadFromClipboardFormat(CF_BITMAP, AMedium.hBitmap, Palette.Palette);
  445. finally
  446. Palette.Free;
  447. end;
  448. Result := True;
  449. end;
  450. function TBitmapClipboardFormat.DoSetData(const FormatEtcIn: TFormatEtc;
  451. var AMedium: TStgMedium): boolean;
  452. var
  453. Palette : HPalette;
  454. Format : Word;
  455. hBitmap : THandle;
  456. begin
  457. Result := False;
  458. try
  459. Format := CF_BITMAP;
  460. FBitmap.SaveToClipboardFormat(Format, hBitmap, Palette);
  461. AMedium.hBitmap := hBitmap;
  462. except
  463. exit;
  464. end;
  465. try
  466. if (Format <> CF_BITMAP) then
  467. begin
  468. DeleteObject(AMedium.hBitmap);
  469. AMedium.hBitmap := 0;
  470. exit;
  471. end;
  472. AMedium.tymed := TYMED_GDI;
  473. finally
  474. DeleteObject(Palette);
  475. end;
  476. Result := True;
  477. end;
  478. ////////////////////////////////////////////////////////////////////////////////
  479. //
  480. // TDIBClipboardFormat
  481. //
  482. ////////////////////////////////////////////////////////////////////////////////
  483. constructor TDIBClipboardFormat.Create;
  484. begin
  485. // Note: We must override Create since base class Create sets tymed to
  486. // TYMED_GDI.
  487. CreateFormat(TYMED_HGLOBAL);
  488. end;
  489. function TDIBClipboardFormat.GetClipboardFormat: TClipFormat;
  490. begin
  491. Result := CF_DIB;
  492. end;
  493. // http://x5.dejanews.com/[ST_rn=ps]/getdoc.xp?AN=382056726.2&CONTEXT=925473183.2090336317&hitnum=0
  494. function TDIBClipboardFormat.DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean;
  495. var
  496. BitmapInfo : PBitmapInfo;
  497. BitmapFileHeader : TBitmapFileHeader;
  498. DIBSize : integer;
  499. FileSize : integer;
  500. InfoSize : integer;
  501. Stream : TMemoryStream;
  502. begin
  503. // Get data source's DIB block
  504. BitmapInfo := GlobalLock(AMedium.HGlobal);
  505. try
  506. Result := (BitmapInfo <> nil);
  507. if (not Result) then
  508. exit;
  509. // Write DIB to a stream in the BMP file format
  510. Stream := TMemoryStream.Create;
  511. try
  512. // Get size of data source's DIB block
  513. DIBSize := GlobalSize(AMedium.HGlobal);
  514. // Calculate total bitmap file size
  515. FileSize := sizeof(TBitmapFileHeader) + DIBSize;
  516. // Calculate bitmap header size
  517. InfoSize := sizeof(TBitmapInfoHeader);
  518. if (BitmapInfo^.bmiHeader.biBitCount > 8) then
  519. begin
  520. if ((BitmapInfo^.bmiHeader.biCompression and BI_BITFIELDS) <> 0) then
  521. Inc(InfoSize, 12);
  522. end else
  523. Inc(InfoSize, sizeof(TRGBQuad) * (1 shl BitmapInfo^.bmiHeader.biBitCount));
  524. Stream.SetSize(FileSize);
  525. // Initialize file header
  526. FillChar(BitmapFileHeader, sizeof(TBitmapFileHeader), 0);
  527. with BitmapFileHeader do
  528. begin
  529. bfType := $4D42; // 'BM' = Windows BMP signature
  530. bfSize := FileSize; // File size (not needed)
  531. bfOffBits := sizeof(TBitmapFileHeader) + InfoSize; // Offset of pixel data
  532. end;
  533. // Save file header
  534. Stream.Write(BitmapFileHeader, sizeof(TBitmapFileHeader));
  535. // Save TBitmapInfo structure and pixel data
  536. Stream.Write(BitmapInfo^, DIBSize);
  537. // Rewind and load bitmap from stream
  538. Stream.Position := 0;
  539. FBitmap.LoadFromStream(Stream);
  540. finally
  541. Stream.Free;
  542. end;
  543. finally
  544. GlobalUnlock(AMedium.HGlobal);
  545. end;
  546. end;
  547. function TDIBClipboardFormat.DoSetData(const FormatEtcIn: TFormatEtc;
  548. var AMedium: TStgMedium): boolean;
  549. begin
  550. AMedium.hBitmap := GetHGlobalDIBFromBitmap(FBitmap);
  551. Result := (AMedium.hBitmap <> 0);
  552. if (Result) then
  553. AMedium.tymed := TYMED_HGLOBAL;
  554. end;
  555. ////////////////////////////////////////////////////////////////////////////////
  556. //
  557. // TCustomMetaFileClipboardFormat
  558. //
  559. ////////////////////////////////////////////////////////////////////////////////
  560. constructor TCustomMetaFileClipboardFormat.Create;
  561. begin
  562. CreateFormat(TYMED_MFPICT);
  563. FMetaFile := TMetaFile.Create;
  564. end;
  565. destructor TCustomMetaFileClipboardFormat.Destroy;
  566. begin
  567. if (FMetaFile <> nil) then
  568. FMetaFile.Free;
  569. inherited Destroy;
  570. end;
  571. procedure TCustomMetaFileClipboardFormat.Clear;
  572. begin
  573. FMetaFile.Clear;
  574. end;
  575. ////////////////////////////////////////////////////////////////////////////////
  576. //
  577. // TMetaFileClipboardFormat
  578. //
  579. ////////////////////////////////////////////////////////////////////////////////
  580. function TMetaFileClipboardFormat.GetClipboardFormat: TClipFormat;
  581. begin
  582. Result := CF_METAFILEPICT;
  583. end;
  584. function WMF2EMF(const MetaFile: TMetaFilePict): hEnhMetaFile;
  585. var
  586. Bits : Pointer;
  587. Length : UINT;
  588. RefDC : HDC;
  589. begin
  590. Length := GetMetaFileBitsEx(MetaFile.hMF, 0, nil);
  591. if (Length = 0) then
  592. _RaiseLastWin32Error;
  593. GetMem(Bits, Length);
  594. try
  595. if (GetMetaFileBitsEx(MetaFile.hMF, Length, Bits) < Length) then
  596. _RaiseLastWin32Error;
  597. RefDC := GetDC(0);
  598. try
  599. Result := SetWinMetaFileBits(Length, Bits, RefDC, MetaFile);
  600. finally
  601. ReleaseDC(0, RefDC);
  602. end;
  603. if (Result = 0) then
  604. _RaiseLastWin32Error;
  605. finally
  606. FreeMem(Bits);
  607. end;
  608. end;
  609. function TMetaFileClipboardFormat.DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean;
  610. var
  611. pMetaFile : PMetaFilePict;
  612. begin
  613. pMetaFile := GlobalLock(AMedium.hMetaFilePict);
  614. try
  615. Result := (pMetaFile <> nil);
  616. if (Result) then
  617. FMetaFile.Handle := WMF2EMF(pMetaFile^);
  618. finally
  619. GlobalUnlock(AMedium.hMetaFilePict);
  620. end;
  621. end;
  622. ////////////////////////////////////////////////////////////////////////////////
  623. //
  624. // TEnhMetaFileClipboardFormat
  625. //
  626. ////////////////////////////////////////////////////////////////////////////////
  627. function TEnhMetaFileClipboardFormat.GetClipboardFormat: TClipFormat;
  628. begin
  629. Result := CF_ENHMETAFILE;
  630. end;
  631. function TEnhMetaFileClipboardFormat.DoGetData(ADataObject: IDataObject; const AMedium: TStgMedium): boolean;
  632. begin
  633. Result := (AMedium.hEnhMetaFile <> 0);
  634. if (Result) then
  635. FMetaFile.Handle := CopyEnhMetafile(AMedium.hEnhMetaFile, nil);
  636. end;
  637. ////////////////////////////////////////////////////////////////////////////////
  638. //
  639. // TBitmapDataFormat
  640. //
  641. ////////////////////////////////////////////////////////////////////////////////
  642. constructor TBitmapDataFormat.Create(AOwner: TDragDropComponent);
  643. begin
  644. inherited Create(AOwner);
  645. FBitmap := TBitmap.Create;
  646. // TGraphic.OnChange is fired too late (after change), but it's the best
  647. // we can get.
  648. FBitmap.OnChange := DoOnChanging;
  649. end;
  650. destructor TBitmapDataFormat.Destroy;
  651. begin
  652. Clear;
  653. FBitmap.Free;
  654. inherited Destroy;
  655. end;
  656. function TBitmapDataFormat.Assign(Source: TClipboardFormat): boolean;
  657. begin
  658. Result := True;
  659. if (Source is TDIBClipboardFormat) then
  660. FBitmap.Assign(TDIBClipboardFormat(Source).Bitmap)
  661. else if (Source is TBitmapClipboardFormat) then
  662. FBitmap.Assign(TBitmapClipboardFormat(Source).Bitmap)
  663. // TODO -oanme : Is this nescessary? Palette is extracted in TBitmapClipboardFormat GetData.
  664. else if (Source is TPaletteClipboardFormat) then
  665. FBitmap.Palette := CopyPalette(TPaletteClipboardFormat(Source).Palette)
  666. else
  667. Result := inherited Assign(Source);
  668. end;
  669. function TBitmapDataFormat.AssignTo(Dest: TClipboardFormat): boolean;
  670. begin
  671. Result := True;
  672. if (Dest is TDIBClipboardFormat) then
  673. TDIBClipboardFormat(Dest).Bitmap.Assign(FBitmap)
  674. else if (Dest is TBitmapClipboardFormat) then
  675. TBitmapClipboardFormat(Dest).Bitmap.Assign(FBitmap)
  676. else if (Dest is TPaletteClipboardFormat) then
  677. TPaletteClipboardFormat(Dest).Palette := CopyPalette(FBitmap.Palette)
  678. else
  679. Result := inherited AssignTo(Dest);
  680. end;
  681. procedure TBitmapDataFormat.Clear;
  682. begin
  683. Changing;
  684. FBitmap.Handle := 0;
  685. end;
  686. function TBitmapDataFormat.HasData: boolean;
  687. begin
  688. Result := (not FBitmap.Empty);
  689. end;
  690. function TBitmapDataFormat.NeedsData: boolean;
  691. begin
  692. Result := (FBitmap.Empty);
  693. end;
  694. ////////////////////////////////////////////////////////////////////////////////
  695. //
  696. // TMetaFileDataFormat
  697. //
  698. ////////////////////////////////////////////////////////////////////////////////
  699. constructor TMetaFileDataFormat.Create(AOwner: TDragDropComponent);
  700. begin
  701. inherited Create(AOwner);
  702. FMetaFile := TMetaFile.Create;
  703. // TGraphic.OnChange is fired too late (after change), but it's the best
  704. // we can get.
  705. FMetaFile.OnChange := DoOnChanging;
  706. end;
  707. destructor TMetaFileDataFormat.Destroy;
  708. begin
  709. Clear;
  710. FMetaFile.Free;
  711. inherited Destroy;
  712. end;
  713. function TMetaFileDataFormat.Assign(Source: TClipboardFormat): boolean;
  714. begin
  715. Result := True;
  716. if (Source is TMetaFileClipboardFormat) then
  717. FMetaFile.Assign(TMetaFileClipboardFormat(Source).MetaFile)
  718. else if (Source is TEnhMetaFileClipboardFormat) then
  719. FMetaFile.Assign(TEnhMetaFileClipboardFormat(Source).MetaFile)
  720. else
  721. Result := inherited Assign(Source);
  722. end;
  723. procedure TMetaFileDataFormat.Clear;
  724. begin
  725. Changing;
  726. FMetaFile.Clear;
  727. end;
  728. function TMetaFileDataFormat.HasData: boolean;
  729. begin
  730. Result := (FMetaFile.Handle <> 0);
  731. end;
  732. function TMetaFileDataFormat.NeedsData: boolean;
  733. begin
  734. Result := (FMetaFile.Handle = 0);
  735. end;
  736. ////////////////////////////////////////////////////////////////////////////////
  737. //
  738. // TDropBMPTarget
  739. //
  740. ////////////////////////////////////////////////////////////////////////////////
  741. constructor TDropBMPTarget.Create(AOwner: TComponent);
  742. begin
  743. inherited Create(AOwner);
  744. FBitmapFormat := TBitmapDataFormat.Create(Self);
  745. end;
  746. destructor TDropBMPTarget.Destroy;
  747. begin
  748. FBitmapFormat.Free;
  749. inherited Destroy;
  750. end;
  751. function TDropBMPTarget.GetBitmap: TBitmap;
  752. begin
  753. Result := FBitmapFormat.Bitmap;
  754. end;
  755. ////////////////////////////////////////////////////////////////////////////////
  756. //
  757. // TDropBMPSource
  758. //
  759. ////////////////////////////////////////////////////////////////////////////////
  760. constructor TDropBMPSource.Create(AOwner: TComponent);
  761. begin
  762. inherited Create(AOwner);
  763. DragTypes := [dtCopy]; // Default to Copy
  764. FBitmapFormat := TBitmapDataFormat.Create(Self);
  765. end;
  766. destructor TDropBMPSource.destroy;
  767. begin
  768. FBitmapFormat.Free;
  769. inherited Destroy;
  770. end;
  771. function TDropBMPSource.GetBitmap: TBitmap;
  772. begin
  773. Result := FBitmapFormat.Bitmap;
  774. end;
  775. procedure TDropBMPSource.SetBitmap(const Value: TBitmap);
  776. begin
  777. FBitmapFormat.Bitmap.Assign(Value);
  778. end;
  779. ////////////////////////////////////////////////////////////////////////////////
  780. //
  781. // TDropMetaFileTarget
  782. //
  783. ////////////////////////////////////////////////////////////////////////////////
  784. constructor TDropMetaFileTarget.Create(AOwner: TComponent);
  785. begin
  786. inherited Create(AOwner);
  787. FMetaFileFormat := TMetaFileDataFormat.Create(Self);
  788. end;
  789. destructor TDropMetaFileTarget.Destroy;
  790. begin
  791. FMetaFileFormat.Free;
  792. inherited Destroy;
  793. end;
  794. function TDropMetaFileTarget.GetMetaFile: TMetaFile;
  795. begin
  796. Result := FMetaFileFormat.MetaFile;
  797. end;
  798. ////////////////////////////////////////////////////////////////////////////////
  799. //
  800. // TDropMetaFileTarget
  801. //
  802. ////////////////////////////////////////////////////////////////////////////////
  803. constructor TDropImageTarget.Create(AOwner: TComponent);
  804. begin
  805. inherited Create(AOwner);
  806. FMetaFileFormat := TMetaFileDataFormat.Create(Self);
  807. FBitmapFormat := TBitmapDataFormat.Create(Self);
  808. FPicture := TPicture.Create;
  809. end;
  810. destructor TDropImageTarget.Destroy;
  811. begin
  812. FPicture.Free;
  813. FBitmapFormat.Free;
  814. FMetaFileFormat.Free;
  815. inherited Destroy;
  816. end;
  817. procedure TDropImageTarget.ClearData;
  818. begin
  819. inherited ClearData;
  820. FPicture.Assign(nil);
  821. end;
  822. function TDropImageTarget.DoGetData: boolean;
  823. begin
  824. Result := inherited DoGetData;
  825. if (Result) then
  826. begin
  827. if (FBitmapFormat.HasData) then
  828. FPicture.Assign(FBitmapFormat.Bitmap)
  829. else if (FMetaFileFormat.HasData) then
  830. FPicture.Assign(FMetaFileFormat.MetaFile)
  831. else
  832. Result := False;
  833. end;
  834. end;
  835. ////////////////////////////////////////////////////////////////////////////////
  836. //
  837. // Initialization/Finalization
  838. //
  839. ////////////////////////////////////////////////////////////////////////////////
  840. initialization
  841. // Data format registration
  842. TBitmapDataFormat.RegisterDataFormat;
  843. TMetaFileDataFormat.RegisterDataFormat;
  844. // Clipboard format registration
  845. TBitmapDataFormat.RegisterCompatibleFormat(TDIBClipboardFormat, 0, csSourceTarget, [ddRead]);
  846. TBitmapDataFormat.RegisterCompatibleFormat(TBitmapClipboardFormat, 1, csSourceTarget, [ddRead]);
  847. TBitmapDataFormat.RegisterCompatibleFormat(TPaletteClipboardFormat, 1, csSourceTarget, [ddRead]);
  848. TMetaFileDataFormat.RegisterCompatibleFormat(TEnhMetaFileClipboardFormat, 0, [csTarget], [ddRead]);
  849. TMetaFileDataFormat.RegisterCompatibleFormat(TMetaFileClipboardFormat, 1, [csTarget], [ddRead]);
  850. finalization
  851. // It is not nescessary to unregister *both* the TClipboardFormats and
  852. // the TTargetFormat, but we do it here to demo how the unregister
  853. // methods are used.
  854. // Clipboard format unregistration
  855. TDIBClipboardFormat.UnregisterClipboardFormat;
  856. TBitmapClipboardFormat.UnregisterClipboardFormat;
  857. TPaletteClipboardFormat.UnregisterClipboardFormat;
  858. TEnhMetaFileClipboardFormat.UnregisterClipboardFormat;
  859. TMetaFileClipboardFormat.UnregisterClipboardFormat;
  860. // Target format unregistration
  861. TBitmapDataFormat.UnregisterDataFormat;
  862. TMetaFileDataFormat.UnregisterDataFormat;
  863. end.