BSMorphButton控件
效果图
单元文件:
unit BSMorphButton;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics,
Controls, Forms, Dialogs , extctrls;
const
Maxize = (1294967280 Div SizeOf(TPoint));
MaxPixelCount = 32768;
Mask0101 = $00FF00FF;
Mask1010 = $FF00FF00;
type
EMorphButton = class(Exception);
PRGBArray = ^TRGBArray;
TRGBArray = array[0..MaxPixelCount-1] of TRGBTriple;
TPnts = array[0..Maxize - 1] of TPoint;
TBSMorphButton = class(TGraphicControl)
private
{Private Declarations}
bmF : TBitmap;
bmT : TBitmap;
bmZ : TBitmap;
FPicFrom : TPicture;
FPicTo : TPicture;
FclFrom : TColor;
FclTo : TColor;
FBRate : integer;
FStretch : Boolean;
FProcMsg : Boolean;
FFinish : Boolean;
FOnBegin : TNotifyEvent;
FOnEnd : TNotifyEvent;
FOnReset : TNotifyEvent;
FAutoRev : Boolean;
FRevSwap : Boolean;
FReverst : Boolean;
FStrTmp : Boolean;
FDelay : integer;
FOnMouseEnter: TNotifyEvent;
FOnMouseLeave: TNotifyEvent;
procedure CMMouseEnter(var Msg:TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Msg:TMessage); message CM_MOUSELEAVE;
procedure chgPicF(Sender : TObject);
procedure chgPicT(Sender : TObject);
procedure WMEraseBkgnd(Var Msg : TMessage); message WM_ERASEBKGND;
procedure SetpicFrom(Pic : TPicture);
procedure SetpicTo(Pic : TPicture);
procedure SetclFrom(Col : TColor);
procedure SetclTo(Col : TColor);
procedure SetBRate(Val : integer);
procedure SetStretch(Val : Boolean);
procedure SetProcMsg(Val : Boolean);
procedure Blend;
procedure UnBlend;
procedure Blendit(bFr,bTo,bLn : Pointer ; Width,Height : Integer ; Dens : LongInt);
protected
procedure WMPosChg(var Msg : TMessage); message WM_WINDOWPOSCHANGED;
public
{Public Declarations}
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
procedure Paint; override;
procedure Reset;
procedure Complete;
property Finish : Boolean read FFinish write FFinish default FALSE;
published
{Published Declarations}
property MorphPic1 : TPicture read FPicFrom write SetpicFrom;
property MorphPic2 : TPicture read FPicTo write SetpicTo;
property MorphColor1 : TColor read FclFrom write SetclFrom default clBlack;
property MorphColor2 : TColor read FclTo write SetclTo default clWhite;
property MorphRate : integer read FBRate write SetBRate default 32;
property StretchToFit : Boolean read FStretch write SetStretch default TRUE;
property ProcessMsgs : Boolean read FProcMsg write SetProcMsg default TRUE;
property Hint;
property OnClick;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Visible;
end;
procedure Register;
{$R Data.res}
implementation
const HandCursor = 31;
Var
EBX, ESI, EDI, ESP, EBP,
FinA,
Dens1, Dens2 : Longint;
constructor TBSMorphButton.Create(AOwner : TComponent);
Var
Temp1:TBitmap;
begin
inherited Create(AOwner);
Screen.Cursors[HandCursor]:=LoadCursor (hInstance , 'CUR');
Cursor:=HandCursor;
FclFrom := clBlack;
FclTo := clWhite;
FBRate := 250;
FStretch := TRUE;
FStrTmp := TRUE;
FProcMsg := TRUE;
FFinish := FALSE;
FAutoRev := FALSE;
FRevSwap := TRUE;
FReverst := FALSE;
FDelay := 1;
ControlStyle := ControlStyle + [csOpaque] + [csNoStdEvents];
Temp1:=TBitmap.Create;
Temp1.LoadFromResourceName (HInstance,'B1');
FPicFrom := TPicture.Create;
FPicFrom.Bitmap:=Temp1;
Temp1.LoadFromResourceName (HInstance,'B2');
FPicTo := TPicture.Create;
FPicTo.Bitmap:=Temp1;
bmF := TBitmap.Create;
bmT := TBitmap.Create;
bmZ := TBitmap.Create;
bmZ.PixelFormat := pf24bit;
bmF.Canvas.Brush.Color := clBlack;
FPicFrom.OnChange := chgPicF;
FPicTo.OnChange := chgPicT;
Width := 120;
Height := 50;
bmF.Width := Width;
bmF.Height := Height;
end;
procedure DoIco(I : TGraphic; B : TBitmap; C : TColor; W : integer; H : integer);
var
bmIco : TBitmap;
begin
bmIco := TBitmap.Create;
bmIco.Width := I.Width;
bmIco.Height := I.Height;
bmIco.Canvas.Brush.Color := C;
bmIco.Canvas.FillRect(RECT(0,0,bmIco.Width,bmIco.Height));
bmIco.Canvas.Draw(0,0,I);
B.Canvas.StretchDraw(RECT(0,0,W,H),bmIco);
bmIco.Free;
end;
procedure TBSMorphButton.Reset;
var
pTmp : TPicture;
cTmp : TColor;
begin
bmF.PixelFormat := pf24bit;
bmT.PixelFormat := pf24bit;
bmZ.PixelFormat := pf24bit;
if FReverst = TRUE then begin
cTmp := FclFrom;
FclFrom := FclTo;
FclTo := cTmp;
pTmp := TPicture.Create;
pTmp.Assign(FPicFrom);
FPicFrom.Assign(FPicTo);
FPicTo.Assign(pTmp);
bmF.Canvas.Brush.Color := FclFrom;
bmT.Canvas.Brush.Color := FclTo;
FReverst := FALSE;
pTmp.Free;
FStretch := FStrTmp;
end;
if FStretch = TRUE then begin
bmF.Width := Width;
bmF.Height := Height;
if FPicFrom.Graphic = nil then
bmF.Canvas.FillRect(RECT(0,0,Width,Height))
else begin
if FPicFrom.Graphic is TMetaFile then
bmF.Canvas.FillRect(RECT(0,0,Width,Height));
if FPicFrom.Graphic is TIcon then begin
DoIco(FPicFrom.Graphic, bmF, FclFrom, Width, Height);
end
else
bmF.Canvas.StretchDraw(RECT(0,0,Width,Height),FPicFrom.Graphic);
end;
bmT.Width := Width;
bmT.Height := Height;
if FPicTo.Graphic = nil then
bmT.Canvas.FillRect(RECT(0,0,Width,Height))
else begin
if FPicTo.Graphic is TMetaFile then
bmT.Canvas.FillRect(RECT(0,0,Width,Height));
if FPicTo.Graphic is TIcon then
DoIco(FPicTo.Graphic, bmT, FclTo, Width, Height)
else
bmT.Canvas.StretchDraw(RECT(0,0,Width,Height),FPicTo.Graphic);
end;
end;
if FStretch = FALSE then begin
if (FPicTo.Graphic <> nil) and (FPicFrom.Graphic = nil) then begin
Width := FPicTo.Width;
Height := FPicTo.Height;
bmT.Width := Width;
bmT.Height := Height;
if (FPicTo.Graphic is TMetaFile) or (FPicTo.Graphic is TIcon) then
bmT.Canvas.FillRect(RECT(0,0,Width,Height));
bmT.Canvas.Draw(0,0,FPicTo.Graphic);
bmF.Width := Width;
bmF.Height := Height;
bmF.Canvas.FillRect(RECT(0,0,Width,Height));
end;
if (FPicFrom.Graphic <> nil) and (FPicTo.Graphic = nil) then begin
Width := FPicFrom.Width;
Height := FPicFrom.Height;
bmF.Width := Width;
bmF.Height := Height;
if (FPicFrom.Graphic is TMetaFile) or (FPicFrom.Graphic is TIcon) then
bmF.Canvas.FillRect(RECT(0,0,Width,Height));
bmF.Canvas.Draw(0,0,FPicFrom.Graphic);
bmT.Width := Width;
bmT.Height := Height;
bmT.Canvas.FillRect(RECT(0,0,Width,Height));
end;
if (FPicFrom.Graphic = nil) and (FPicTo.Graphic = nil) then begin
bmF.Width := Width;
bmF.Height := Height;
bmF.Canvas.FillRect(RECT(0,0,Width,Height));
bmT.Width := Width;
bmT.Height := Height;
bmT.Canvas.FillRect(RECT(0,0,Width,Height));
end;
if (FPicFrom.Graphic <> nil) and (FPicTo.Graphic <> nil) then begin
Width := FPicFrom.Width;
Height := FPicFrom.Height;
bmF.Width := Width;
bmF.Height := Height;
if (FPicFrom.Graphic is TMetaFile) or (FPicFrom.Graphic is TIcon) then
bmF.Canvas.FillRect(RECT(0,0,Width,Height));
bmF.Canvas.Draw(0,0,FPicFrom.Graphic);
bmT.Width := Width;
bmT.Height := Height;
if FPicTo.Graphic is TMetaFile then
bmT.Canvas.FillRect(RECT(0,0,Width,Height));
if FPicTo.Graphic is TIcon then begin
DoIco(FPicTo.Graphic, bmT, FclTo, Width, Height);
end
else
bmT.Canvas.StretchDraw(RECT(0,0,Width,Height),FPicTo.Graphic);
end;
end;
bmZ.Width := bmF.Width;
bmZ.Height := bmF.Height;
Invalidate;
if Assigned (FOnReset) then FOnReset(Self);
end;
procedure TBSMorphButton.WMEraseBkgnd(var Msg:TMessage);
begin
Msg.Result := 1;
end;
procedure TBSMorphButton.Paint;
begin
Canvas.Draw(0,0,bmF);
Canvas.Brush.Style:=bsClear;
end;
procedure TBSMorphButton.Complete;
begin
Canvas.Draw(0,0,bmT);
if Assigned (FOnEnd) then FOnEnd(Self);
FFinish := FALSE;
end;
Function Pt(B : TBitmap) : Pointer;
Begin
Pt := B.Scanline[(B.Height-1)]
End;
procedure TBSMorphButton.Blendit(bFr,bTo,bLn : Pointer ; Width,Height : Integer ; Dens : LongInt); assembler;
ASM
MOV &EBX, EBX
MOV &EDI, EDI
MOV &ESI, ESI
MOV &ESP, ESP
MOV &EBP, EBP
MOV EBX, Dens
MOV Dens1, EBX
NEG BL
ADD BL, $20
MOV Dens2, EBX
CMP Dens1, 0
JZ @Final
MOV EDI, bFr
MOV ESI, bTo
MOV ECX, bLn
MOV EAX, Width
lea EAX, [EAX+EAX*2+3]
AND EAX, $FFFFFFFC
IMUL Height
ADD EAX, EDI
MOV FinA, EAX
MOV EBP,EDI
MOV ESP,ESI
MOV ECX,ECX
@LOOPA:
MOV EAX, [EBP]
MOV EDI, [ESP]
MOV EBX, EAX
AND EAX, Mask1010
AND EBX, Mask0101
SHR EAX, 5
IMUL EAX, Dens2
IMUL EBX, Dens2
MOV ESI, EDI
AND EDI, Mask1010
AND ESI, Mask0101
SHR EDI, 5
IMUL EDI, Dens1
IMUL ESI, Dens1
ADD EAX, EDI
ADD EBX, ESI
AND EAX, Mask1010
SHR EBX, 5
AND EBX, Mask0101
OR EAX, EBX
MOV [ECX], EAX
ADD EBP, 4
ADD ESP, 4
ADD ECX, 4
CMP EBP, FinA
JNE @LOOPA
@FINAL:
MOV EBX, &EBX
MOV EDI, &EDI
MOV ESI, &ESI
MOV ESP, &ESP
MOV EBP, &EBP
End;
procedure TBSMorphButton.Blend;
var
r : integer;
begin
Reset;
if FBRate < 1 then
raise EMorphButton.Create('BlendRate must be between 0 and 256');
if Assigned (FOnBegin) then FOnBegin(Self);
bmZ.Canvas.Draw(0, 0, bmF);
for r := 0 to FBRate do begin
Blendit(Pt(bmZ),Pt(bmT),Pt(bmF),bmF.Width,bmF.Height,(r*$20 Div FBRate));
RePaint;
if FProcMsg = TRUE then
Application.ProcessMessages;
if FFinish = TRUE then begin
Complete;
Exit;
end;
end;
if FAutoRev = TRUE then begin
Sleep(FDelay * 1000);
end;
if Assigned (FOnEnd) then FOnEnd(Self);
end;
procedure TBSMorphButton.UnBlend;
var
r : integer;
pTmp : TPicture;
cTmp : TColor;
begin
FStrTmp := FStretch;
FStretch := TRUE;
bmF.Canvas.Brush.Color := FclTo;
bmT.Canvas.Brush.Color := FclFrom;
cTmp := FclFrom;
FclFrom := FclTo;
FclTo := cTmp;
pTmp := TPicture.Create;
pTmp.Assign(FPicFrom);
FPicFrom.Assign(FPicTo);
FPicTo.Assign(pTmp);
pTmp.Free;
Reset;
FReverst := TRUE;
bmZ.Canvas.Draw(0, 0, bmF);
for r := 0 to FBRate do begin
Blendit(Pt(bmZ),Pt(bmT),Pt(bmF),bmF.Width,bmF.Height,(r*$20 Div FBRate));
RePaint;
if FProcMsg = TRUE then
Application.ProcessMessages;
if FFinish = TRUE then begin
Complete;
Exit;
end;
end;
Reset;
end;
procedure TBSMorphButton.WMPosChg(var Msg : TMessage);
begin
Reset;
Invalidate;
inherited;
end;
procedure TBSMorphButton.CMMouseEnter(var Msg:TMessage);
begin
inherited;
if Assigned (FOnMouseEnter) then FOnMouseEnter(Self);
Blend;
end;
procedure TBSMorphButton.CMMouseLeave(var Msg:TMessage);
begin
inherited;
if Assigned (FonMouseLeave) then FOnMouseLeave(Self);
UnBlend;
end;
procedure TBSMorphButton.chgPicF(Sender : TObject);
begin
if FReverst = TRUE then Exit;
Reset;
Invalidate;
end;
procedure TBSMorphButton.chgPicT(Sender : TObject);
begin
if FReverst = TRUE then Exit;
Reset;
Invalidate;
end;
procedure TBSMorphButton.SetpicFrom(Pic : TPicture);
begin
FPicFrom.Assign(Pic);
end;
procedure TBSMorphButton.SetpicTo(Pic : TPicture);
begin
FPicTo.Assign(Pic);
end;
procedure TBSMorphButton.SetclFrom(Col : TColor);
begin
if FclFrom <> Col then begin
FclFrom := Col;
bmF.Canvas.Brush.Color := Col;
Reset;
Invalidate;
end;
end;
procedure TBSMorphButton.SetclTo(Col : TColor);
begin
if FclTo <> Col then begin
FclTo := Col;
bmT.Canvas.Brush.Color := Col;
Reset;
Invalidate;
end;
end;
procedure TBSMorphButton.SetBRate(Val : integer);
begin
if FBRate <> Val then
FBRate := Val;
if FBRate < 1 then
FBRate := 1;
if FBRate > 255 then
FBRate := 255;
end;
procedure TBSMorphButton.SetStretch(Val : Boolean);
begin
if FStretch <> Val then begin
FStretch := Val;
Reset;
Invalidate;
end;
end;
procedure TBSMorphButton.SetProcMsg(Val : Boolean);
begin
if FProcMsg <> Val then
FProcMsg := Val;
end;
destructor TBSMorphButton.Destroy;
begin
FPicFrom.Free;
FPicTo.Free;
bmF.Free;
bmT.Free;
bmZ.Free;
inherited Destroy;
end;
procedure Register;
begin
RegisterComponents('Samples', [TBSMorphButton]);
end;
end.
资源文件下载: