| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- unit DragDropBitmap;
- {
- Description
- ===========
- TDragDropBitmap is a component for simple OLE drag-and-drop operations
- with bitmaps. The component is a child-class from TDragDrop.
- Disclaimer
- ==========
- The author disclaims all warranties, expressed or implied, including,
- without limitation, the warranties of merchantability and of fitness
- for any purpose. The author assumes no liability for damages, direct or
- consequential, which may result from the use of this component/unit.
- Restrictions on Using the Unit / Component
- ==========================================
- This unit/component is copyright 1998 by Dieter Steinwedel. ALL RIGHTS
- ARE RESERVED BY DIETER STEINWEDEL. You are allowed to use it freely
- subject to the following restrictions:
- • You are not allowed delete or alter the author's name and
- copyright in any manner
- • You are not allowed to publish a copy, modified version or
- compilation neither for payment in any kind nor freely
- • You are allowed to create a link to the download in the WWW
- • These restrictions and terms apply to you as long as until
- I alter them. Changes can found on my homepage
- Contact
- =======
- homepage: http://godard.oec.uni-osnabrueck.de/student_home/dsteinwe/delphi/DietersDelphiSite.htm
- }
- {$ALIGN ON}
- {$ASSERTIONS OFF}
- {$BOOLEVAL OFF}
- {$DENYPACKAGEUNIT OFF}
- {$EXTENDEDSYNTAX ON}
- {$HINTS ON}
- {$IMPORTEDDATA ON}
- {$LONGSTRINGS ON}
- {$OPTIMIZATION ON}
- {$TYPEDADDRESS OFF}
- {$TYPEINFO OFF}
- {$WARNINGS ON}
- interface
- uses DragDrop, Windows, Classes, SysUtils, ActiveX, Graphics, Controls, Forms;
- type
- TDataObjectBitmap = class(TDataObject)
- private
- DIBStream:TMemoryStream;
- public
- constructor Create(const Bitmap: TBitmap);
- destructor Destroy; override;
- function RenderData(FormatEtc:TFormatEtc;
- var StgMedium: TStgMedium):HResult; override;
- end;
- TDropTargetBitmap = class(TDropTarget)
- protected
- procedure AcceptDataObject(DataObj: IDataObject; var Accept:boolean); override;
- public
- constructor Create(AOwner: TDragDrop);
- destructor Destroy; override;
- procedure RenderDropped(DataObj: IDataObject; grfKeyState: Longint;
- pt: TPoint; var dwEffect: longint); override;
- end;
- TDragDropBitmap = class(TDragDrop)
- private
- FBitmap:TBitmap;
- procedure SetBitmap(Bitmap:TBitmap);
- protected
- function CreateDataObject:TDataObject; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- property Bitmap: TBitmap read FBitmap write SetBitmap;
- end;
- procedure Register;
- implementation
- // some local functions --------------------------------------------------------
- {procedure CopyAsBitmap(Bitmap:TBitmap; DataPtr: PChar; DataSize:longint);
- var MemoryStream: TMemoryStream;
- BMF: TBitmapFileheader;
- begin
- ZeroMemory(@BMF, sizeof (TBitmapFileheader));
- BMF.bfType:=$4D42;
- MemoryStream:=TMemoryStream.Create;
- try
- MemoryStream.Write(BMF, sizeof (BMF));
- MemoryStream.Write(DataPtr^, DataSize);
- MemoryStream.Seek(0,0);
- Bitmap.LoadFromStream(MemoryStream);
- finally
- MemoryStream.Free;
- end;
- end;}
- procedure CopyAsBitmap(Bitmap:TBitmap; DataPtr: PChar; DataSize:longint);
- var BitmapInfoHeader: TBitmapInfoHeader;
- BitmapInfo: PBitmapInfo;
- Size: Word;
- Pal: HPALETTE;
- BitsMem: Pointer;
- Focus: HWND;
- DC: HDC;
- OldPal: HPALETTE;
- ImagePtr:pchar;
- ImageSize:DWord;
- function GetDInColors(BitCount: Word): Integer;
- begin
- case BitCount of
- 1, 4, 8: Result := 1 shl BitCount;
- else Result := 0;
- end;
- end;
- function PaletteFromW3DIB(const BI: TBitmapInfo): HPALETTE;
- var DstPal: PLogPalette;
- Colors, n: Integer;
- Size: Longint;
- DC: HDC;
- Focus: HWND;
- SysPalSize: Integer;
- I: Integer;
- begin
- Result := 0;
- { If the ClrUsed field of the header is non-zero, it means that we could
- have a short color table }
- with BI.bmiHeader do
- if biClrUsed <> 0 then Colors := biClrUsed
- else Colors := GetDInColors(biBitCount);
- if Colors <= 2 then Exit;
- Size := SizeOf(TLogPalette) + ((Colors - 1) * SizeOf(TPaletteEntry));
- DstPal := AllocMem(Size);
- try
- FillChar(DstPal^, Size, 0);
- with DstPal^ do
- begin
- palNumEntries := Colors;
- palVersion := $300;
- Focus := GetFocus;
- DC := GetDC(Focus);
- try
- SysPalSize := GetDeviceCaps(DC, SIZEPALETTE);
- if (Colors = 16) and (SysPalSize >= 16) then
- begin
- { Ignore the disk image of the palette for 16 color bitmaps use
- instead the first 8 and last 8 of the current system palette }
- GetSystemPaletteEntries(DC, 0, 8, palPalEntry);
- I := 8;
- GetSystemPaletteEntries(DC, SysPalSize - I, I, palPalEntry[I]);
- end
- else
- { Copy the palette for all others (i.e. 256 colors) }
- for N := 0 to Colors - 1 do
- begin
- palPalEntry[N].peRed := BI.bmiColors[N].rgbRed;
- palPalEntry[N].peGreen := BI.bmiColors[N].rgbGreen;
- palPalEntry[N].peBlue := BI.bmiColors[N].rgbBlue;
- palPalEntry[N].peFlags := 0;
- end;
- finally
- ReleaseDC(Focus, DC);
- end;
- end;
- Result := CreatePalette(DstPal^);
- finally
- FreeMem(DstPal, Size);
- end;
- end;
- begin
- ImagePtr:=DataPtr;
- ImageSize:=DataSize;
- CopyMemory(@BitmapInfoHeader,ImagePtr,SizeOf(TBitmapInfoHeader));
- ImagePtr:=ImagePtr+SizeOf(TBitmapInfoHeader);
- with BitmapInfoHeader do
- begin
- if biClrUsed = 0 then
- biClrUsed := GetDInColors(biBitCount);
- Size := biClrUsed * SizeOf(TRgbQuad);
- end;
- BitmapInfo := AllocMem(Size + SizeOf(TBitmapInfoHeader));
- try
- with BitmapInfo^ do
- begin
- bmiHeader := BitmapInfoHeader;
- CopyMemory(@bmiColors, ImagePtr,Size);
- ImagePtr:=ImagePtr+Size;
- { now we've got the color table. Create a palette from it }
- Pal := PaletteFromW3DIB(BitmapInfo^);
- { some applications do not fill in the SizeImage field in the header.
- (Actually the truth is more likely that some drivers do not fill the field
- in and the apps do not compensate for these buggy drivers.) Therefore, if
- this field is 0, we will compute the size. }
- with bmiHeader do
- begin
- Dec(ImageSize, SizeOf(TBitmapInfoHeader) + Size);
- if biSizeImage <> 0 then
- if biSizeImage < ImageSize then ImageSize := biSizeImage;
- BitsMem := AllocMem(ImageSize);
- try
- CopyMemory(BitsMem, ImagePtr,ImageSize);
- { we use the handle of the window with the focus (which, if this routine
- is called from a menu command, will be this window) in order to guarantee
- that the realized palette will have first priority on the system palette }
- Focus := GetFocus;
- DC := GetDC(Focus);
- if DC <>0 then
- try
- if Pal <> 0 then
- begin
- { select and realize our palette we have gotten the DC of the focus
- window just to make sure that all our colors are mapped }
- OldPal := SelectPalette(DC, Pal, False);
- RealizePalette(DC);
- end
- else OldPal := 0;
- try
- Bitmap.Handle:=CreateDIBitmap(DC, BitmapInfo^.bmiHeader, CBM_INIT, BitsMem,
- BitmapInfo^, DIB_RGB_COLORS);
- finally
- if OldPal <> 0 then
- SelectPalette(DC, OldPal, False);
- end;
- finally
- ReleaseDC(Focus, DC);
- end;
- finally
- FreeMem(BitsMem, ImageSize);
- end;
- end;
- end;
- finally
- FreeMem(BitmapInfo, Size + SizeOf(TBitmapInfoHeader));
- end;
- end;
- function WidthBytes(I: Longint): Longint;
- begin
- Result := ((I + 31) div 32) * 4;
- end;
- procedure InitializeBitmapInfoHeader(Bitmap: HBITMAP; var BI: TBitmapInfoHeader;
- Colors: Integer);
- var BM: Windows.TBitmap;
- begin
- GetObject(Bitmap, SizeOf(BM), @BM);
- with BI do
- begin
- biSize := SizeOf(BI);
- biWidth := BM.bmWidth;
- biHeight := BM.bmHeight;
- if Colors <> 0 then
- case Colors of
- 2: biBitCount := 1;
- 16: biBitCount := 4;
- 256: biBitCount := 8;
- end
- else biBitCount := BM.bmBitsPixel * BM.bmPlanes;
- biPlanes := 1;
- biXPelsPerMeter := 0;
- biYPelsPerMeter := 0;
- biClrUsed := 0;
- biClrImportant := 0;
- biCompression := BI_RGB;
- if biBitCount in [16, 32] then biBitCount := 24;
- biSizeImage := WidthBytes(biWidth * biBitCount) * biHeight;
- end;
- end;
- procedure InternalGetDIBSizes(Bitmap: HBITMAP; var InfoHeaderSize: Integer;
- var ImageSize: DWORD; Colors: Integer);
- var BI: TBitmapInfoHeader;
- begin
- InitializeBitmapInfoHeader(Bitmap, BI, Colors);
- with BI do
- begin
- if biBitCount=24 then InfoHeaderSize := SizeOf(TBitmapInfoHeader)
- else InfoHeaderSize := SizeOf(TBitmapInfoHeader) + SizeOf(TRGBQuad) *
- (1 shl biBitCount);
- end;
- ImageSize := BI.biSizeImage;
- end;
- function InternalGetDIB(Bitmap: HBITMAP; Palette: HPALETTE;
- var BitmapInfo; var Bits; Colors: Integer): Boolean;
- var OldPal: HPALETTE;
- Focus: HWND;
- DC: HDC;
- begin
- InitializeBitmapInfoHeader(Bitmap, TBitmapInfoHeader(BitmapInfo), Colors);
- OldPal := 0;
- Focus := GetFocus;
- DC := GetDC(Focus);
- try
- if Palette <> 0 then
- begin
- OldPal := SelectPalette(DC, Palette, False);
- RealizePalette(DC);
- end;
- Result := GetDIBits(DC, Bitmap, 0, TBitmapInfoHeader(BitmapInfo).biHeight,
- @Bits, TBitmapInfo(BitmapInfo), DIB_RGB_COLORS) <> 0;
- finally
- if OldPal <> 0 then SelectPalette(DC, OldPal, False);
- ReleaseDC(Focus, DC);
- end;
- end;
- procedure DIBFromBit(Stream: TMemoryStream; Src: HBITMAP;
- Pal: HPALETTE; Colors: Integer; var DIBHeader, DIBBits: Pointer);
- var HeaderSize: Integer;
- ImageSize: DWORD;
- begin
- if Src=0 then exit;
- InternalGetDIBSizes(Src, HeaderSize, ImageSize, Colors);
- Stream.SetSize(HeaderSize + integer(ImageSize));
- DIBHeader:=Stream.Memory;
- DIBBits:=Pointer(Longint(DIBHeader) + HeaderSize);
- InternalGetDIB(Src, Pal, DIBHeader^, DIBBits^, Colors);
- end;
- // TDataObjectBitmap -----------------------------------------------------------
- constructor TDataObjectBitmap.Create(const Bitmap: TBitmap);
- var FE:TFormatEtc;
- SM:TStgMedium;
- DIBHeader, DIBBits: Pointer;
- begin
- inherited Create;
- with FE do
- begin
- cfFormat:=CF_DIB;
- ptd:=nil;
- dwAspect:=DVASPECT_CONTENT;
- lindex:=-1;
- tymed:=TYMED_HGLOBAL;
- end;
- SetData(FE,SM,false);
- DIBStream:=TMemoryStream.Create;
- DIBFromBit(DIBStream, Bitmap.Handle, Bitmap.Palette,0,DIBHeader, DIBBits);
- // Don't release DIBHeader and DIBBits; both points to a position in the stream
- end;
- destructor TDataObjectBitmap.Destroy;
- begin
- DIBStream.free;
- inherited Destroy;
- end;
- function TDataObjectBitmap.RenderData(FormatEtc:TFormatEtc;
- var StgMedium: TStgMedium):HResult;
- var h: HGlobal;
- p:pointer;
- begin
- Result:=E_Fail;
- if FormatEtc.cfFormat=cf_DIB then
- begin
- h:=GlobalAlloc(GHND or GMEM_SHARE, DIBStream.Size);
- if h=0 then
- begin
- Result:=E_OUTOFMEMORY;
- exit;
- end;
- p:=globallock(h);
- DIBStream.Seek(0,0);
- DIBStream.Read(p^,DIBStream.Size);
- globalunlock(h);
- with StgMedium do
- begin
- tymed:=TYMED_HGLOBAL;
- hGlobal := h;
- unkForRelease := nil;
- end;
- Result:=S_OK;
- end;
- end;
- // TDropTargetBitmap -----------------------------------------------------------
- constructor TDropTargetBitmap.Create(AOwner: TDragDrop);
- begin
- inherited Create(AOwner);
- end;
- destructor TDropTargetBitmap.Destroy;
- begin
- inherited Destroy;
- end;
- procedure TDropTargetBitmap.AcceptDataObject(DataObj: IDataObject; var Accept:boolean);
- var FE:TFormatEtc;
- begin
- with FE do
- begin
- cfFormat:=cf_DIB;
- ptd:=nil;
- dwAspect:=DVASPECT_CONTENT;
- lindex:=-1;
- tymed:=TYMED_HGLOBAL;
- end;
- Accept:=DataObj.QueryGetData(FE)=S_OK;
- end;
- procedure TDropTargetBitmap.RenderDropped(DataObj: IDataObject; grfKeyState: Longint;
- pt: TPoint; var dwEffect: longint);
- var FE: TFormatEtc;
- SM: TStgMedium;
- DataSize: longint;
- DataPtr: pointer;
- begin
- with FE do
- begin
- cfFormat:=CF_DIB;
- ptd:=nil;
- dwAspect:=DVASPECT_CONTENT;
- lindex:=-1;
- tymed:=TYMED_HGLOBAL;
- end;
- if DataObj.GetData(FE,SM)=S_Ok then
- begin
- DataSize:=GlobalSize(SM.HGlobal);
- try
- DataPtr:=GlobalLock(SM.HGlobal);
- CopyAsBitmap(TDragDropBitmap(FOwner).FBitmap,DataPtr, DataSize);
- finally
- GlobalUnLock(SM.HGlobal);
- ReleaseStgMedium(SM);
- end;
- end;
- end;
- // TDragDropBitmap -------------------------------------------------------------
- constructor TDragDropBitmap.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FBitmap:=TBitmap.Create;
- FDropTarget._Release;
- FDropTarget:=TDropTargetBitmap.Create(self);
- end;
- destructor TDragDropBitmap.Destroy;
- begin
- FBitmap.free;
- inherited destroy;
- end;
- procedure TDragDropBitmap.SetBitmap(Bitmap:TBitmap);
- var MS:TMemoryStream;
- begin
- // A little bit dirty but short ...
- MS:=TMemoryStream.Create;
- Bitmap.SaveToStream(MS);
- MS.Seek(0,0);
- FBitmap.LoadFromStream(MS);
- MS.Free;
- end;
- function TDragDropBitmap.CreateDataObject:TDataObject;
- begin
- if FBitmap.Empty=false then Result:=TDataObjectBitmap.Create(FBitmap)
- else Result:=nil;
- end;
- // Register --------------------------------------------------------------------
- procedure Register;
- begin
- {MP}RegisterComponents({'Shell32'}'DragDrop', [TDragDropBitmap]);
- end;
- end.
|