unit RXUtils; //Some functions from RX's VCLUtils.Pas; {$IFNDEF VER80} {-- Delphi 1.0 } {$IFNDEF VER90} {-- Delphi 2.0 } {$IFNDEF VER93} {-- C++Builder 1.0 } {$DEFINE RX_D3} { Delphi 3.0 or higher } {$ENDIF} {$ENDIF} {$ENDIF} {$P+,W-,R-,V-} interface {$IFDEF WIN32} uses Windows, Classes, Graphics; {$ELSE} uses WinTypes, WinProcs, Classes, Graphics; {$ENDIF} { Windows resources (bitmaps and icons) VCL-oriented routines } procedure DrawBitmapTransparent(Dest: TCanvas; DstX, DstY: Integer; Bitmap: TBitmap; TransparentColor: TColor); { Service routines } function Max(X, Y: Integer): Integer; function Min(X, Y: Integer): Integer; { Standard Windows colors that are not defined by Delphi } const {$IFNDEF WIN32} clInfoBk = TColor($02E1FFFF); clNone = TColor($02FFFFFF); {$ENDIF} clCream = TColor($A6CAF0); clMoneyGreen = TColor($C0DCC0); clSkyBlue = TColor($FFFBF0); implementation { Service routines } function Max(X, Y: Integer): Integer; begin if X > Y then Result := X else Result := Y; end; function Min(X, Y: Integer): Integer; begin if X < Y then Result := X else Result := Y; end; function PaletteColor(Color: TColor): Longint; const { TBitmap.GetTransparentColor from GRAPHICS.PAS use this value } PaletteMask = $02000000; begin Result := ColorToRGB(Color) or PaletteMask; end; { Transparent bitmap } procedure StretchBltTransparent(DstDC: HDC; DstX, DstY, DstW, DstH: Integer; SrcDC: HDC; SrcX, SrcY, SrcW, SrcH: Integer; Palette: HPalette; TransparentColor: TColorRef); var Color: TColorRef; bmAndBack, bmAndObject, bmAndMem, bmSave: HBitmap; bmBackOld, bmObjectOld, bmMemOld, bmSaveOld: HBitmap; MemDC, BackDC, ObjectDC, SaveDC: HDC; palDst, palMem, palSave, palObj: HPalette; begin { Create some DCs to hold temporary data } BackDC := CreateCompatibleDC(DstDC); ObjectDC := CreateCompatibleDC(DstDC); MemDC := CreateCompatibleDC(DstDC); SaveDC := CreateCompatibleDC(DstDC); { Create a bitmap for each DC } bmAndObject := CreateBitmap(SrcW, SrcH, 1, 1, nil); bmAndBack := CreateBitmap(SrcW, SrcH, 1, 1, nil); bmAndMem := CreateCompatibleBitmap(DstDC, DstW, DstH); bmSave := CreateCompatibleBitmap(DstDC, SrcW, SrcH); { Each DC must select a bitmap object to store pixel data } bmBackOld := SelectObject(BackDC, bmAndBack); bmObjectOld := SelectObject(ObjectDC, bmAndObject); bmMemOld := SelectObject(MemDC, bmAndMem); bmSaveOld := SelectObject(SaveDC, bmSave); { Select palette } palDst := 0; palMem := 0; palSave := 0; palObj := 0; if Palette <> 0 then begin palDst := SelectPalette(DstDC, Palette, True); RealizePalette(DstDC); palSave := SelectPalette(SaveDC, Palette, False); RealizePalette(SaveDC); palObj := SelectPalette(ObjectDC, Palette, False); RealizePalette(ObjectDC); palMem := SelectPalette(MemDC, Palette, True); RealizePalette(MemDC); end; { Set proper mapping mode } SetMapMode(SrcDC, GetMapMode(DstDC)); SetMapMode(SaveDC, GetMapMode(DstDC)); { Save the bitmap sent here } BitBlt(SaveDC, 0, 0, SrcW, SrcH, SrcDC, SrcX, SrcY, SRCCOPY); { Set the background color of the source DC to the color, } { contained in the parts of the bitmap that should be transparent } Color := SetBkColor(SaveDC, PaletteColor(TransparentColor)); { Create the object mask for the bitmap by performing a BitBlt() } { from the source bitmap to a monochrome bitmap } BitBlt(ObjectDC, 0, 0, SrcW, SrcH, SaveDC, 0, 0, SRCCOPY); { Set the background color of the source DC back to the original } SetBkColor(SaveDC, Color); { Create the inverse of the object mask } BitBlt(BackDC, 0, 0, SrcW, SrcH, ObjectDC, 0, 0, NOTSRCCOPY); { Copy the background of the main DC to the destination } BitBlt(MemDC, 0, 0, DstW, DstH, DstDC, DstX, DstY, SRCCOPY); { Mask out the places where the bitmap will be placed } StretchBlt(MemDC, 0, 0, DstW, DstH, ObjectDC, 0, 0, SrcW, SrcH, SRCAND); { Mask out the transparent colored pixels on the bitmap } BitBlt(SaveDC, 0, 0, SrcW, SrcH, BackDC, 0, 0, SRCAND); { XOR the bitmap with the background on the destination DC } StretchBlt(MemDC, 0, 0, DstW, DstH, SaveDC, 0, 0, SrcW, SrcH, SRCPAINT); { Copy the destination to the screen } BitBlt(DstDC, DstX, DstY, DstW, DstH, MemDC, 0, 0, SRCCOPY); { Restore palette } if Palette <> 0 then begin SelectPalette(MemDC, palMem, False); SelectPalette(ObjectDC, palObj, False); SelectPalette(SaveDC, palSave, False); SelectPalette(DstDC, palDst, True); end; { Delete the memory bitmaps } DeleteObject(SelectObject(BackDC, bmBackOld)); DeleteObject(SelectObject(ObjectDC, bmObjectOld)); DeleteObject(SelectObject(MemDC, bmMemOld)); DeleteObject(SelectObject(SaveDC, bmSaveOld)); { Delete the memory DCs } DeleteDC(MemDC); DeleteDC(BackDC); DeleteDC(ObjectDC); DeleteDC(SaveDC); end; procedure StretchBitmapTransparent(Dest: TCanvas; Bitmap: TBitmap; TransparentColor: TColor; DstX, DstY, DstW, DstH, SrcX, SrcY, SrcW, SrcH: Integer); var CanvasChanging: TNotifyEvent; Temp: TBitmap; begin if DstW <= 0 then DstW := Bitmap.Width; if DstH <= 0 then DstH := Bitmap.Height; if (SrcW <= 0) or (SrcH <= 0) then begin SrcX := 0; SrcY := 0; SrcW := Bitmap.Width; SrcH := Bitmap.Height; end; if not Bitmap.Monochrome then SetStretchBltMode(Dest.Handle, STRETCH_DELETESCANS); CanvasChanging := Bitmap.Canvas.OnChanging; try Bitmap.Canvas.OnChanging := nil; Temp := Bitmap; try if TransparentColor = clNone then begin StretchBlt(Dest.Handle, DstX, DstY, DstW, DstH, Temp.Canvas.Handle, SrcX, SrcY, SrcW, SrcH, Dest.CopyMode); end else begin {$IFDEF RX_D3} if TransparentColor = clDefault then TransparentColor := Temp.Canvas.Pixels[0, Temp.Height - 1]; {$ENDIF} if Temp.Monochrome then TransparentColor := clWhite else TransparentColor := ColorToRGB(TransparentColor); StretchBltTransparent(Dest.Handle, DstX, DstY, DstW, DstH, Temp.Canvas.Handle, SrcX, SrcY, SrcW, SrcH, Temp.Palette, TransparentColor); end; finally end; finally Bitmap.Canvas.OnChanging := CanvasChanging; end; end; procedure DrawBitmapTransparent(Dest: TCanvas; DstX, DstY: Integer; Bitmap: TBitmap; TransparentColor: TColor); begin StretchBitmapTransparent(Dest, Bitmap, TransparentColor, DstX, DstY, Bitmap.Width, Bitmap.Height, 0, 0, Bitmap.Width, Bitmap.Height); end; end.