Recent

Author Topic: MaskEdit exceptions  (Read 23849 times)

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
MaskEdit exceptions
« on: November 17, 2010, 09:39:17 pm »
When a MaskEdit is being filled and then exited from, while not all required characters are filled, an exception is being generated. Now, I'd like to create an exception handler, but I don't get WHERE would I put the try..except block! I can see no point in the source where the program flow would meet that condition. I guess something roughly like this would be required:
Code: [Select]
try
  MaskEdit1.OnExit
except
...

But like I said, I see no positions in the code where that exception could be caught. Am I missing something here?  %)
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: MaskEdit exceptions
« Reply #1 on: November 18, 2010, 01:15:53 pm »
In the OnExit event of the Maskedit you van check if the text validates, and if not then correct the text (or do a reset).
Making sure the control has a valid text is the only way to avoid the exception.

Non tested example:

Code: [Select]
procedure MaskEdit1Exit(Sender: TObject);
var
  S: String;
begin
  try
    MaskEdit1.ValidateEdit;
  Except
    S := MaskEdit1.Text;
    MaskEdit1.Reset;
    ShowMessage(S + 'does not match the specified format, please try again.');
  end;
end;

This behaviour (throwing the exception when loosing focus) is also present in Delphi, but there you cannot intercept the exception in OnExit: the exception is raised before the event is fired).
It is not very user friendly, I know. I find it a particular annoying habit of the control.

If you want, you can get rid of the exception: rebuild the LCL with MASKEDIT_NOVALIDATEONEXIT as a conditional define (see maskedit.pp).
No more validation wil be done when loosing focus.
You can still manually invoke SomeEditMask.ValidateEdit to perform the validation.

Or you can handle the exception in your global applications exceptionhandler.


Bart

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
Re: MaskEdit exceptions
« Reply #2 on: November 18, 2010, 10:43:47 pm »
Thanks Bart, you've clarified some things to me. Yes, the component's behavior is really annoying in this regard. I wouldn't like to use a modified LCL as not to break Delphi (and regular LCL for that matter) compatibility.

If I understand you correctly, you say that actually there is no way to catch LCL's MaskEdit exception on any particular event, except using a global handler? I guess the proper way for catching this particular exception would be validation in "BeforeExit" event if it existed...

So, there really no place exists to catch an exception OnExit event throws?
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: MaskEdit exceptions
« Reply #3 on: November 19, 2010, 01:43:41 pm »
I'm afraid it is.

In Delphi you cannot even catch the exception in the OnExit, so Lazarus behaves just a little nicer (at least I thought so, when I implemented it this way).

If anyone knows a better solution to catch the exception in a more developer frindly way, I'ld be glad to know.

Bart

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
Re: MaskEdit exceptions
« Reply #4 on: November 19, 2010, 05:42:42 pm »
Well, I guess that means Delphi has a flaw. Since Lazarus need not be just a Delphi clone, why not improve that ;)

You said before that Delphi throws the exception before OnExit, but that seems quite logical... At what point does Lazarus do that? After OnExit?

Whatever the answer, this is one of the situations that make me feel I don't have a complete control of the code in Delphi/Lazarus. Events are handled somewhere in a "black box" and I  cannot influence what happens then... :( It seems there is no point in my source where I could put the code I wrote in the first post... <rant> In the good old procedural programming, you always had control except while calling an external routine, yet you never lose control of the program flow... </rant> This can be frustrating. It's a shame really...
« Last Edit: November 19, 2010, 05:46:12 pm by TurboRascal »
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: MaskEdit exceptions
« Reply #5 on: November 20, 2010, 10:01:59 am »
Well, I guess that means Delphi has a flaw. Since Lazarus need not be just a Delphi clone, why not improve that ;)

You said before that Delphi throws the exception before OnExit, but that seems quite logical... At what point does Lazarus do that? After OnExit?

What I meant is that in Delphi, when the control looses focus, validation is performed, the exception is raised if validation fails, and only after that the the OnExit handler is called.

In Lazarus I changed this sequence to focus lost -> call OnExit handler -> perform validation -> raise exception when validation fails.

So, where in Delphi you cannot prevent or intercept the exception in any of the MaskEdit event handlers, in Lazarus at least you can do so in the OnExit eventhandler.

Another thing is that the unhandled exception only causes a simple dialog to appear in Delphi prompting you to press escape, whilst in Lazarus the default dialog appears inviting you to kill the application or continue and risk dataloss, which for the end user is confusing to say the least.

To remain compatible with Delphi, it is however necessary to raise the exception when validation fails. This is how programmers expect it to be.
I'm not really sure why the Borland guys choose to use an exception, rather then simply doing a showmessage.
But we'll have to live with that.

Events are handled somewhere in a "black box" and I  cannot influence what happens then...

But you can. You can extend / override the default application exception handler.
I must say I never did this, but AFAIK it should be possible.

Pseudocode:

Code: [Select]
Procedure NewExceptionhandler(...);
begin
  if Exception is EDBEditError then
  begin
    do a simple showmessage
  end
  else call the OldExceptionHandler
end;
 

Bart

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
Re: MaskEdit exceptions
« Reply #6 on: November 20, 2010, 03:59:15 pm »
What I meant is that in Delphi, when the control looses focus, validation is performed, the exception is raised if validation fails, and only after that the the OnExit handler is called.

In Lazarus I changed this sequence to focus lost -> call OnExit handler -> perform validation -> raise exception when validation fails.

So, where in Delphi you cannot prevent or intercept the exception in any of the MaskEdit event handlers, in Lazarus at least you can do so in the OnExit eventhandler.

I've researched a bit more, and it seems validation is done at the OnValidate event which also happens, supposedly before OnExit, but I need to check that. That way, if I Validate manually there, then handle the exception and abort the procedure if exception fires, I guess I could handle that... Do you know in which sequence those events happen?

Another thing is that the unhandled exception only causes a simple dialog to appear in Delphi
...
I'm not really sure why the Borland guys choose to use an exception, rather then simply doing a showmessage.

Yes, it is strange... Seems just like they wanted to make lifes of programmers using MaskEdit miserable  :D Instead of returning some warning messages and/or setting a Boolean, they used an exception that is not easy to handle in that context...

But you can. You can extend / override the default application exception handler.

Yes, I know I could have used a global exception handler, but I just wanted to try handle it locally instead, which turned out to be a lot more harder :)
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: MaskEdit exceptions
« Reply #7 on: November 20, 2010, 09:34:10 pm »
I've researched a bit more, and it seems validation is done at the OnValidate event which also happens, supposedly before OnExit, but I need to check that. That way, if I Validate manually there, then handle the exception and abort the procedure if exception fires, I guess I could handle that... Do you know in which sequence those events happen?

I modelled the Lazarus MaskEdit using Delphi using a black box method.
I examined the behaviour of it, then made our MaskEdit do the same.
In Delphi 3 (I do not have any more recent version, further more I have Win9x, so recent Delphi's won't run on my computer) do not have the OnValidate event.

If you can test what the sequence is, and if you can prevent the exception (and how) in the OnValidate eventhandler, I can (try to) implement this in lazarus too.

What happens in Delphi when you do the following (especiallly: do you still get a validation error?):

(code not tested)

Code: [Select]
procedure MaskEdit1Validate(Sender: TObject); //OnValidate handler
begin
  showmessage('OnValidate');
  MaskEdit1.Text := 'some text you know is valid'; // <-- not literally this text !
end;

procedure MaskEdit1Exit(Sender: TObject); //OnExit handler
begin
  ShowMessage('OnExit');
end;

B.t.w. I don't see an OnValidate event in Embarcadero's VCL reference.

Bart

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
Re: MaskEdit exceptions
« Reply #8 on: November 21, 2010, 12:53:25 am »
I'll check all that in Delphi and then I'll get back to you.
Btw. are you sure you cannot install newer than D3 on w98? I believe up to D7 can be installed on 9x... I could doublecheck that too...
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: MaskEdit exceptions
« Reply #9 on: November 21, 2010, 10:22:52 am »
I have D3 Pro and the free D6/D7 will not let you install components in the IDE.
Furthermore I have WinME, which tends be become rather unstable whenever I try to install software, so I hardly do that.

Last but not least, I hardly use D3 anymore, I prefer Lazarus/Fpc.

Bart

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: MaskEdit exceptions
« Reply #10 on: November 21, 2010, 12:41:21 pm »
Maybe a construction like this might be applicable?

Code: [Select]
  TForm1 = class(TForm)
    MaskEdit1: TMaskEdit;
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
    procedure ExceptionHandler(Sender : TObject; E : Exception);
  public
    { public declarations }
  end;

...
implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnException := @ExceptionHandler;
end;

procedure TForm1.ExceptionHandler(Sender: TObject; E: Exception);
var
  S: String;
begin
  if E is EDBEditError then
  begin
    if ActiveControl is TMaskEdit then
    begin
      S := (ActiveControl as TMaskEdit).Text;
      ShowMessage(E.Message+':'^m'"'+S+'"')
    end
    else ShowMessage(E.Message);
  end
  else Application.ShowException(E);
end;   


Bart

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
Re: MaskEdit exceptions
« Reply #11 on: November 22, 2010, 03:49:05 am »
You were right, there is no OnValidate, I got a wrong information which I didn't check before posting  :-[

I will try your code, and when I investigate a bit more, I'll report back here  ;)
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

 

TinyPortal © 2005-2018