joely
asked on
Make more perfect
How to make this component looks like TButton.
In TButton after OnClick event, it will go up without wait a process completed.
To see the difference try to put this component in form1 (as a procedure) and call form2 (form2.showmodal).
This component looked "down" and after close form2, it will be back go up.
unit TButton;
interface
uses
Windows, Messages, Classes, Graphics, Controls, ExtCtrls;
type
TButtonState=(bsUp,bsDown) ;
TAlignment=(taLeft,taCente r,taRight) ;
type
TTButton = class(TGraphicControl)
private
FAlignment: TAlignment;
FCaption: TCaption;
FTransparent: Boolean;
FWordWrap: Boolean;
FMouseDown: Boolean;
FMouseInside: Boolean;
FState: TButtonState;
FInsideButton: Boolean;
procedure SetAlignment(Value:TAlignm ent);
procedure SetCaption(Value:TCaption) ;
procedure SetTransparent(Value:boole an);
procedure SetWordWrap(Value:boolean) ;
protected
procedure DrawTheText;
function InsideBtn(X,Y: Integer): boolean;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer);override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
procedure Click; override;
published
property Alignment:TAlignment read FAlignment write SetAlignment default taCenter;
property Caption: TCaption read FCaption write SetCaption;
property Enabled;
property Font;
property ShowHint;
property Transparent: boolean read FTransparent write SetTransparent default True;
property Visible;
property WordWrap:boolean read FWordWrap write SetWordWrap default False;
property OnClick;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
end;
procedure Register;
implementation
constructor TTButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle - [csOpaque];
FState := bsUp;
FMouseInside := False;
SetBounds(0,0,60,30);
FAlignment := taCenter;
FTransparent := True;
FMouseDown:= False;
FInsideButton := False;
FWordwrap := False;
end;
procedure TTButton.SetAlignment(Valu e:TAlignme nt);
begin
if FAlignment <> Value then
begin
FAlignment := Value;
Invalidate;
end;
end;
procedure TTButton.SetCaption(Value: TCaption);
begin
if FCaption <> Value then
begin
FCaption := Value;
Invalidate;
end;
end;
procedure TTButton.SetTransparent(Va lue:boolea n);
begin
if FTransparent <> Value then
begin
if Value then
ControlStyle := ControlStyle - [csOpaque]
else
ControlStyle := ControlStyle + [csOpaque];
FTransparent := Value;
Invalidate;
end;
end;
procedure TTButton.SetWordWrap(Value :boolean);
begin
if FWordWrap <> Value then
begin
FWordwrap := Value;
Invalidate;
end;
end;
function TTButton.InsideBtn(X,Y: Integer): boolean;
begin
Result := PtInRect(Rect(0,0,Width,He ight),Poin t(X,Y));
end;
procedure TTButton.Paint;
var
TmpRect:TRect;
begin
TmpRect := Rect(0,0,Width,Height);
with Canvas do
begin
Brush.Color := clBtnFace;
Pen.Color := clBlack;
Pen.Width := 1;
Pen.Color := clBlack;
if not Transparent then
Rectangle(1,1,Width,Height )
else
begin
TmpRect := Rect(1,1,Width,Height);
Frame3D(Canvas,TmpRect,clB lack,clBla ck,1);
end;
TmpRect := Rect(1,1,Width-1,Height-1) ;
if (FState = bsDown) then
begin
InflateRect(TmpRect,1,1);
Frame3D(Canvas,TmpRect,clB lack,clBtn HighLight, 1);
Frame3D(Canvas,TmpRect,clB tnShadow,c lBtnFace,1 );
end;
if (FState = bsUp) then
begin
TmpRect := Rect(1,1,Width-1,Height-1) ;
InflateRect(TmpRect,1,1);
Frame3D(Canvas,TmpRect,clB tnHighLigh t,clBlack, 1);
Frame3D(Canvas,TmpRect,clB tnFace,clB tnShadow,1 );
end;
end;
DrawTheText;
end;
procedure TTButton.DrawTheText;
var
Flags,MidX,MidY: Integer;
DC: THandle;
Tmprect: TRect;
begin
Canvas.Font := Self.Font;
DC := Canvas.Handle;
if FWordWrap then
Flags := DT_WORDBREAK
else
Flags := DT_SINGLELINE;
TmpRect := Rect(0,0,Width,Height);
DrawText(DC, PChar(FCaption), Length(FCaption), TmpRect, Flags or DT_CALCRECT);
MidY := TmpRect.Bottom - TmpRect.Top;
MidX := TmpRect.Right - TmpRect.Left;
Flags := DT_CENTER;
case Alignment of
taLeft:
OffsetRect(TmpRect,0,Heigh t div 2 - MidY div 2);
taCenter:
OffsetRect(TmpRect,Width div 2 - MidX div 2,Height div 2 - MidY div 2);
taRight:
OffsetRect(TmpRect,Width - MidX,Height div 2 - MidY div 2);
end;
if FWordWrap then
Flags := Flags or DT_WORDBREAK or DT_NOCLIP
else
Flags := Flags or DT_SINGLELINE or DT_NOCLIP;
if FState = bsDown then
OffsetRect(TmpRect,1,1);
SetBkMode(DC,Windows.TRANS PARENT);
if not Enabled then
begin
SetTextColor(DC,ColorToRGB (clBtnHigh Light));
OffsetRect(tmpRect,1,1);
DrawText(DC, PChar(FCaption), Length(FCaption), TmpRect, Flags);
OffsetRect(TmpRect,-1,-1);
SetTextColor(DC,ColorToRGB (clBtnShad ow));
end
else
SetTextColor(DC,self.Font. Color);
DrawText(DC, PChar(FCaption), Length(FCaption), TmpRect, Flags);
end;
procedure TTButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if not Enabled then Exit;
inherited MouseDown(Button,Shift,X,Y );
if Assigned(OnMouseDown) then OnMouseDown(Self,Button,Sh ift,X,Y);
if InsideBtn(X,Y) then
begin
FMouseDown := True;
FState := bsDown;
Repaint;
end;
end;
procedure TTButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if not Enabled then Exit;
inherited MouseUp(Button,Shift,X,Y);
FMouseDown := False;
FState := bsUp;
Repaint;
if Assigned(OnMouseUp) then OnMouseUp(Self,Button,Shif t,X,Y);
end;
procedure TTButton.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
inherited MouseMove(Shift,X,Y);
if Assigned(OnMouseMove) then OnMouseMove(Self,Shift,X,Y );
if FMouseDown then
begin
if not InsideBtn(X,Y) then
begin
if FState = bsDown then
begin
FState := bsUp;
Repaint;
end;
end
else
begin
if FState = bsUp then
begin
FState := bsDown;
Repaint;
end;
end;
end;
end;
procedure TTButton.Click;
begin
inherited Click;
end;
procedure Register;
begin
RegisterComponents('Sample s', [TTButton]);
end;
end.
In TButton after OnClick event, it will go up without wait a process completed.
To see the difference try to put this component in form1 (as a procedure) and call form2 (form2.showmodal).
This component looked "down" and after close form2, it will be back go up.
unit TButton;
interface
uses
Windows, Messages, Classes, Graphics, Controls, ExtCtrls;
type
TButtonState=(bsUp,bsDown)
TAlignment=(taLeft,taCente
type
TTButton = class(TGraphicControl)
private
FAlignment: TAlignment;
FCaption: TCaption;
FTransparent: Boolean;
FWordWrap: Boolean;
FMouseDown: Boolean;
FMouseInside: Boolean;
FState: TButtonState;
FInsideButton: Boolean;
procedure SetAlignment(Value:TAlignm
procedure SetCaption(Value:TCaption)
procedure SetTransparent(Value:boole
procedure SetWordWrap(Value:boolean)
protected
procedure DrawTheText;
function InsideBtn(X,Y: Integer): boolean;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer);override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
procedure Click; override;
published
property Alignment:TAlignment read FAlignment write SetAlignment default taCenter;
property Caption: TCaption read FCaption write SetCaption;
property Enabled;
property Font;
property ShowHint;
property Transparent: boolean read FTransparent write SetTransparent default True;
property Visible;
property WordWrap:boolean read FWordWrap write SetWordWrap default False;
property OnClick;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
end;
procedure Register;
implementation
constructor TTButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle - [csOpaque];
FState := bsUp;
FMouseInside := False;
SetBounds(0,0,60,30);
FAlignment := taCenter;
FTransparent := True;
FMouseDown:= False;
FInsideButton := False;
FWordwrap := False;
end;
procedure TTButton.SetAlignment(Valu
begin
if FAlignment <> Value then
begin
FAlignment := Value;
Invalidate;
end;
end;
procedure TTButton.SetCaption(Value:
begin
if FCaption <> Value then
begin
FCaption := Value;
Invalidate;
end;
end;
procedure TTButton.SetTransparent(Va
begin
if FTransparent <> Value then
begin
if Value then
ControlStyle := ControlStyle - [csOpaque]
else
ControlStyle := ControlStyle + [csOpaque];
FTransparent := Value;
Invalidate;
end;
end;
procedure TTButton.SetWordWrap(Value
begin
if FWordWrap <> Value then
begin
FWordwrap := Value;
Invalidate;
end;
end;
function TTButton.InsideBtn(X,Y: Integer): boolean;
begin
Result := PtInRect(Rect(0,0,Width,He
end;
procedure TTButton.Paint;
var
TmpRect:TRect;
begin
TmpRect := Rect(0,0,Width,Height);
with Canvas do
begin
Brush.Color := clBtnFace;
Pen.Color := clBlack;
Pen.Width := 1;
Pen.Color := clBlack;
if not Transparent then
Rectangle(1,1,Width,Height
else
begin
TmpRect := Rect(1,1,Width,Height);
Frame3D(Canvas,TmpRect,clB
end;
TmpRect := Rect(1,1,Width-1,Height-1)
if (FState = bsDown) then
begin
InflateRect(TmpRect,1,1);
Frame3D(Canvas,TmpRect,clB
Frame3D(Canvas,TmpRect,clB
end;
if (FState = bsUp) then
begin
TmpRect := Rect(1,1,Width-1,Height-1)
InflateRect(TmpRect,1,1);
Frame3D(Canvas,TmpRect,clB
Frame3D(Canvas,TmpRect,clB
end;
end;
DrawTheText;
end;
procedure TTButton.DrawTheText;
var
Flags,MidX,MidY: Integer;
DC: THandle;
Tmprect: TRect;
begin
Canvas.Font := Self.Font;
DC := Canvas.Handle;
if FWordWrap then
Flags := DT_WORDBREAK
else
Flags := DT_SINGLELINE;
TmpRect := Rect(0,0,Width,Height);
DrawText(DC, PChar(FCaption), Length(FCaption), TmpRect, Flags or DT_CALCRECT);
MidY := TmpRect.Bottom - TmpRect.Top;
MidX := TmpRect.Right - TmpRect.Left;
Flags := DT_CENTER;
case Alignment of
taLeft:
OffsetRect(TmpRect,0,Heigh
taCenter:
OffsetRect(TmpRect,Width div 2 - MidX div 2,Height div 2 - MidY div 2);
taRight:
OffsetRect(TmpRect,Width - MidX,Height div 2 - MidY div 2);
end;
if FWordWrap then
Flags := Flags or DT_WORDBREAK or DT_NOCLIP
else
Flags := Flags or DT_SINGLELINE or DT_NOCLIP;
if FState = bsDown then
OffsetRect(TmpRect,1,1);
SetBkMode(DC,Windows.TRANS
if not Enabled then
begin
SetTextColor(DC,ColorToRGB
OffsetRect(tmpRect,1,1);
DrawText(DC, PChar(FCaption), Length(FCaption), TmpRect, Flags);
OffsetRect(TmpRect,-1,-1);
SetTextColor(DC,ColorToRGB
end
else
SetTextColor(DC,self.Font.
DrawText(DC, PChar(FCaption), Length(FCaption), TmpRect, Flags);
end;
procedure TTButton.MouseDown(Button:
begin
if not Enabled then Exit;
inherited MouseDown(Button,Shift,X,Y
if Assigned(OnMouseDown) then OnMouseDown(Self,Button,Sh
if InsideBtn(X,Y) then
begin
FMouseDown := True;
FState := bsDown;
Repaint;
end;
end;
procedure TTButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if not Enabled then Exit;
inherited MouseUp(Button,Shift,X,Y);
FMouseDown := False;
FState := bsUp;
Repaint;
if Assigned(OnMouseUp) then OnMouseUp(Self,Button,Shif
end;
procedure TTButton.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
inherited MouseMove(Shift,X,Y);
if Assigned(OnMouseMove) then OnMouseMove(Self,Shift,X,Y
if FMouseDown then
begin
if not InsideBtn(X,Y) then
begin
if FState = bsDown then
begin
FState := bsUp;
Repaint;
end;
end
else
begin
if FState = bsUp then
begin
FState := bsDown;
Repaint;
end;
end;
end;
end;
procedure TTButton.Click;
begin
inherited Click;
end;
procedure Register;
begin
RegisterComponents('Sample
end;
end.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ja - that's the problem. described in your last sentence. i mean, this was obvious, waddaya think?...
;-)
Black Death.
;-)
Black Death.
Well... it's not really a problem. That's actually how event-handling in a component is supposed to work...
. Oops! you were joking weren't you? O.K. I'm a little slow on the uptake. I mean, with a name like Black Death (and a cool name it is) I wasn't expecting a good sense of humor. Sorry.
;-)
. Oops! you were joking weren't you? O.K. I'm a little slow on the uptake. I mean, with a name like Black Death (and a cool name it is) I wasn't expecting a good sense of humor. Sorry.
;-)
no prob, hellforge.
i'm quite a punch...
in fact, my humor's as black as my soul.
that makes me a little bit unwieldy in most people's opinion.
those people rather like my back than my front.
so those people never come to know me.
which is perfectly ok, cos those people are mostly the kind i really don't care of.
who cares anyway - those people dying young are longer dead...
>;->
that's enuff of that stuff.
have a nice day,
Black Death.
i'm quite a punch...
in fact, my humor's as black as my soul.
that makes me a little bit unwieldy in most people's opinion.
those people rather like my back than my front.
so those people never come to know me.
which is perfectly ok, cos those people are mostly the kind i really don't care of.
who cares anyway - those people dying young are longer dead...
>;->
that's enuff of that stuff.
have a nice day,
Black Death.
afaik, for tbutton (via twincontrol via tcontrol) this is handled by the messaging system and windows' standard styles... (?)
i don't think there's a proper way to make your code run as intended.
sorry, that wasn't much help.
bye,
Black Death.