Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programatically show Balloon Hint only for invalid text edit input

Tags:

hint

delphi

I'm following this example: http://lawrencebarsanti.wordpress.com/2009/12/16/display-error-messages-with-tballoonhint/

I'm trying to only show a balloon hint when the current value in the edit box is not acceptable. The check is triggered when OnExit. The balloon should still be allowed to display until the value is determined to be OK. I'm also trying to programmatically show the balloon as soon as the user leaves the edit to show the initial error.

The code works, but not the first time. I have to leave once with an invalid value, change to an acceptable one, then come back and use an invalid one again. I think this is because I can't enable or disable the ShowHint property right before I try 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 right when I check for a valid value (leaving the edit)?

like image 547
ikathegreat Avatar asked Aug 12 '14 15:08

ikathegreat


1 Answers

Actually, the thing that's odd is that you get anything the second time, not that you don't get anything the first.

Your code works for me (in XE4 & XE6) 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 did work for you second time around, I think it's because of code you're not showing, and equally something you're not showing is probably why it doesn't work the first. So you can "spot the difference", the code of my project is below. I couldn't find your StrIsReal function so rolled my own.

Btw, I added a second TEdit to my form, so that there is something else on it to lose focus to, and commented out your two Edit1.ShowHint assignments as they don't make any difference but shouldn't be necessary 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;
like image 185
MartynA Avatar answered Sep 27 '22 22:09

MartynA