Programmatically show a hint on the ball only for invalid text input
I'm following this example: http://lawrencebarsanti.wordpress.com/2009/12/16/display-error-messages-with-tballoonhint/
I am trying to show only the balloon when the current value in the edit box is not acceptable. The check is triggered when OnExit
. The balloon is still allowed to be displayed until the value is determined to be OK. I am also trying to programmatically show the balloon as soon as the user leaves edit to show the initial error.
The code works, but not the first time. I have to go away once with an invalid value, change to an acceptable one, then go back and use the invalid value again. I think this is because I cannot enable or disable the ShowHint property right before trying to show the balloon.
Here is my code:
procedure TForm1.Edit1Exit(Sender: TObject);
var
R: TRect;
Bad : Boolean;
begin
//Check if edit has only numbers
if StrIsReal(Edit1.Text) then
begin
if(StrToFloat(Edit1.Text) >= 0.5) then
begin
//Value is ok
SpeedButton1.Visible := false;
Edit1.ShowHint := false;
BalloonHint1.HideHint;
Edit1.Text := FloatToStrF(StrToFloat(Edit1.Text), ffFixed, 8, 2);
end
else
begin
//Is decimal, but not at least 0.5
Bad := true;
end;
end
else
begin
Bad := true;
end;
if Bad then
begin
//Invalid number
Edit1.ShowHint := true;
Edit1.Text := '0.00';
SpeedButton1.Visible := true;
R := Edit1.BoundsRect;
R.TopLeft := ClientToScreen(R.TopLeft);
R.BottomRight := ClientToScreen(R.BottomRight);
BalloonHint1.ShowHint(R); //!!! Issue: No hint the first time around
end;
end;
How can I show the balloon conditionally correct when I check the actual value (leaving editing)?
source to share
Actually, the thing that is strange is that you get something the second time, and not that you don't get anything the first.
Your code works for me (in XE4 and XE6) the first time (and second) with this change:
R := Edit1.BoundsRect;
R.TopLeft := ClientToScreen(R.TopLeft);
R.BottomRight := ClientToScreen(R.BottomRight);
BalloonHint1.Description := 'bad input'; <---- this was missing
BalloonHint1.ShowHint(R); //!!! Issue: No hint the first time around
So, if it worked for you the second time around, I guess it is because of the code you are not showing and equally what you are not showing is probably why it does not work in the first place. So you can "spot the difference" with my project code below. I couldn't find your StrIsReal function, so I made my own.
Btw, I added a second TEdit to my form so there is something else to lose focus, and commented out your two Edit1.ShowHint assignments as they don't make any difference but shouldn't be needed anyway.
TForm1 = Class(TForm)
[...]
FBalloonHint : TBalloonHint;
procedure WMActivateApp(var AMessage: TMessage); message WM_ActivateApp;
procedure WMWindowPosChanged(var AMessage: TMessage); message WM_WindowPosChanged;
[...]
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FBalloonHint := TBalloonHint.Create(Self);
FBalloonHint.HideAfter := 5000;
FBalloonHint.Delay := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
R: TRect;
begin
FBalloonHint.Description := 'You pressed ' + Button1.Caption;
R := Button1.BoundsRect;
R.TopLeft := ClientToScreen(R.TopLeft);
R.BottomRight := ClientToScreen(R.BottomRight);
FBalloonHint.ShowHint(R);
end;
procedure TForm1.Edit1Exit(Sender: TObject);
var
R: TRect;
Bad : Boolean;
F : Double;
function StrIsReal(S : String) : Boolean;
begin
Result := True;
end;
begin
//Check if edit has only numbers
if StrIsReal(Edit1.Text) then
begin
if(StrToFloat(Edit1.Text) >= 0.5) then
begin
//Value is ok
SpeedButton1.Visible := false;
//Edit1.ShowHint := false;
FBalloonHint.HideHint;
Edit1.Text := FloatToStrF(StrToFloat(Edit1.Text), ffFixed, 8, 2);
end
else
begin
//Is decimal, but not at least 0.5
Bad := true;
end;
end
else
begin
Bad := true;
end;
if Bad then
begin
//Invalid number
//Edit1.ShowHint := true;
Edit1.Text := '0.00';
SpeedButton1.Visible := true;
R := Edit1.BoundsRect;
R.TopLeft := ClientToScreen(R.TopLeft);
R.BottomRight := ClientToScreen(R.BottomRight);
FBalloonHint.Description := 'bad input';
FBalloonHint.ShowHint(R); //!!! Issue: No hint the first time around
end;
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Edit1Exit(Sender);
end;
procedure TForm1.WMActivateApp(var AMessage: TMessage);
begin
if Assigned(FBalloonHint) then FBalloonHint.HideHint;
inherited;
end;
procedure TForm1.WMWindowPosChanged(var AMessage: TMessage);
begin
if Assigned(FBalloonHint) then FBalloonHint.HideHint;
inherited;
end;
source to share