Unit USrv; interface uses Windows, Classes, Graphics, Controls, Messages, Dialogs, SysUtils; const WM_GETIMAGE = WM_USER + $0429; function BitmapToRegion(Bitmap: TBitmap): HRGN; function CopyToBitmap(Control: TControl; Bitmap: TBitmap; Anyway: boolean): boolean; procedure CopyParentImage(Control: TControl; Dest: TCanvas); procedure RestoreImage(DestDC: HDC; SrcBitmap: TBitmap; r: TRect; dwROP: dword); overload; procedure RestoreImage(DestDC: HDC; SrcBitmap: TBitmap; l, t, w, h: integer; dwROP: dword); overload; procedure AjustBitmap(const M: TBitmap; S, C: TColor); procedure FadeBitmap(const M: TBitmap; C: TColor; D: byte); function IncColor(C: TColor; D: integer): TColor; implementation function BitmapToRegion(Bitmap: TBitmap): HRGN; var X, Y: Integer; XStart: Integer; TransC: TColor; R: HRGN; begin Result := 0; with Bitmap do begin TransC := Canvas.Pixels[0, 0]; for Y := 0 to Height - 1 do begin X := 0; while X < Width do begin while (X < Width) and (Canvas.Pixels[X, Y] = TransC) do Inc(X); if X >= Width then Break; XStart := X; while (X < Width) and (Canvas.Pixels[X, Y] <> TransC) do Inc(X); R := CreateRectRgn(XStart, Y, X, Y + 1); if Result = 0 then Result := R else begin CombineRgn(Result, Result, R, RGN_OR); DeleteObject(R); end; end; end; end; end; function CopyToBitmap; var x, y: integer; begin Result := False; if Control = nil then exit; x := BitMap.Width - 2; y := BitMap.Height - 2; if (Anyway) or (x + 2 <> Control.Width) or (y + 2 <> Control.Height) or (BitMap.Canvas.Pixels[x, y] = $FFFFFF) or (BitMap.Canvas.Pixels[x, y] = $000000) then begin BitMap.Width := Control.Width; BitMap.Height := Control.Height; CopyParentImage(Control, BitMap.Canvas); Result := True; end; end; type TParentControl = class(TWinControl); procedure CopyParentImage(Control: TControl; Dest: TCanvas); var I, Count, X, Y, SaveIndex: Integer; DC: HDC; R, SelfR, CtlR: TRect; begin if (Control = nil) or (Control.Parent = nil) then Exit; Count := Control.Parent.ControlCount; DC := Dest.Handle; with Control.Parent do ControlState := ControlState + [csPaintCopy]; try with Control do begin SelfR := Bounds(Left, Top, Width, Height); X := -Left; Y := -Top; end; { Copy parent control image } SaveIndex := SaveDC(DC); try if TParentControl(Control.Parent).Perform( WM_GETIMAGE, DC, integer(@SelfR)) <> $29041961 then begin SetViewportOrgEx(DC, X, Y, nil); IntersectClipRect(DC, 0, 0, Control.Parent.ClientWidth, Control.Parent.ClientHeight); with TParentControl(Control.Parent) do begin Perform(WM_ERASEBKGND, DC, 0); PaintWindow(DC); end; end; finally RestoreDC(DC, SaveIndex); end; { Copy images of graphic controls } for I := 0 to Count - 1 do begin if Control.Parent.Controls[I] = Control then continue else if (Control.Parent.Controls[I] <> nil) and (Control.Parent.Controls[I] is TGraphicControl) then begin with TGraphicControl(Control.Parent.Controls[I]) do begin CtlR := Bounds(Left, Top, Width, Height); if Bool(IntersectRect(R, SelfR, CtlR)) and Visible then begin ControlState := ControlState + [csPaintCopy]; SaveIndex := SaveDC(DC); try if Perform( WM_GETIMAGE, DC, integer(@SelfR)) <> $29041961 then begin { SaveIndex := SaveDC(DC);} SetViewportOrgEx(DC, Left + X, Top + Y, nil); IntersectClipRect(DC, 0, 0, Width, Height); Perform(WM_PAINT, DC, 0); end; finally RestoreDC(DC, SaveIndex); ControlState := ControlState - [csPaintCopy]; end; end; end; end; end; finally with Control.Parent do ControlState := ControlState - [csPaintCopy]; end; end; procedure RestoreImage(DestDC: HDC; SrcBitmap: TBitmap; r: TRect; dwROP: dword); overload; begin RestoreImage(DestDC, SrcBitmap, r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top, dwROP); end; procedure RestoreImage(DestDC: HDC; SrcBitmap: TBitmap; l, t, w, h: integer; dwROP: dword); overload; var x, y: integer; begin x := l + w div 2; y := t + h div 2; if (SrcBitmap.Canvas.Pixels[x, y] <> $FFFFFF) and (SrcBitMap.Canvas.Pixels[x, y] <> $000000) then begin x := l; y := t; if y + h > SrcBitMap.Height then begin y := SrcBitMap.Height - h; end; bitblt(DestDC, l, t, w, h, SrcBitMap.Canvas.Handle, x, y, dwROP); end; end; procedure SplitColor(C: TColor; var r, g, b: integer); begin b := (c and $FF0000) shr 16; g := (c and $00FF00) shr 08; r := (c and $0000FF) shr 00; end; procedure AjustBitmap; var i, j: integer; t: TBitmap; r, g, b, r2, g2, b2: integer; p: PRGBTriple; function CalcColor(c1, c2, c3: integer): integer; begin if c1 = c3 then begin Result := c2; exit; end; if c1 = 0 then begin Result := 0; exit; end; { Result := 255 * c1 div c3 - c1 * (255 - c1) * (255 - c2) div c3 div (255 - c3); exit;} Result := c1 * c2 div c3; if c2 = 0 then Result := c1 * 150 div 255; if Result > 255 then Result := 255; if Result < 50 then Result := Result + 50; { exit; a := trunc(x1 * 3); a := c1 * (255 - c1) * c2 * (255 - c2) div c3 div (255 - c3); a := 255 * 255 - 4 * a; try x1 := Trunc((255 - sqrt(a)) / 2); x2 := Trunc((255 + sqrt(a)) / 2); if x1 > x2 then Result := Trunc(x1) else Result := Trunc(x2); except Result := 0; end;} end; begin if s = c then exit; if m.Width = 0 then exit; if m.Height = 0 then exit; t := TBitmap.Create; m.PixelFormat := pf24bit; t.Assign(m); SplitColor(ColorToRGB(s), r, g, b); if r = 0 then r := 1; if g = 0 then g := 1; if b = 0 then b := 1; SplitColor(ColorToRGB(c), r2, g2, b2); for j := 0 to t.Height - 1 do begin p := t.scanline[j]; for i := 0 to t.Width - 1 do begin p.rgbtRed := CalcColor(p.rgbtRed, r2, r); p.rgbtGreen := CalcColor(p.rgbtGreen, g2, g); p.rgbtBlue := CalcColor(p.rgbtBlue, b2, b); inc(p); end; end; m.Assign(t); t.Free; end; procedure FadeBitmap; var i, j: integer; t: TBitmap; r, g, b: integer; p: PRGBTriple; function CalcColor(o: byte; c: byte; b: byte): byte; var d: byte; begin Result := c; if o > c then begin d := $FF - c; if d > b then d := b; Result := c + c * d div 255; end else if o < c then begin d := c; if d > b then d := b; Result := c - c * d div 255; end; end; begin if m.Width = 0 then exit; if m.Height = 0 then exit; t := TBitmap.Create; m.PixelFormat := pf24bit; t.Assign(m); SplitColor(ColorToRGB(c), r, g, b); if r = 0 then r := 1; if g = 0 then g := 1; if b = 0 then b := 1; for j := 0 to t.Height - 1 do begin p := t.scanline[j]; for i := 0 to t.Width - 1 do begin p.rgbtRed := CalcColor(p.rgbtRed, r, d); p.rgbtGreen := CalcColor(p.rgbtGreen, g, d); p.rgbtBlue := CalcColor(p.rgbtBlue, b, d); inc(p); end; end; m.Assign(t); t.Free; end; function IncColor; var T: TColor; P: PRGBTriple; begin T := ColorToRGB(C); p := @T; if D > 0 then begin if p.rgbtBlue < 255 - D then p.rgbtBlue := p.rgbtBlue + D else p.rgbtBlue := 255; if p.rgbtRed < 255 - D then p.rgbtRed := p.rgbtRed + D else p.rgbtRed := 255; if p.rgbtGreen < 255 - D then p.rgbtGreen := p.rgbtGreen + D else p.rgbtGreen := 255; end else begin if p.rgbtBlue > D then p.rgbtBlue := p.rgbtBlue - D else p.rgbtBlue := 000; if p.rgbtRed > D then p.rgbtRed := p.rgbtRed - D else p.rgbtRed := 000; if p.rgbtGreen > D then p.rgbtGreen := p.rgbtGreen - D else p.rgbtGreen := 000; end; Result := T; end; end.