Subversion Repositories decoder

Rev

Blame | Last modification | View Log | RSS feed

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