Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ignore timer events in Delphis MessageDlg

I have set up a global exception handler in Delphi. On some severe exceptions an error message is displayed (followed by Halt()). While the error message is shown, Delphi is processing the message queue, processing timer events, that lead to further errors.

What I want is to show an error dialog which does not process timer events. How is that possible in Delphi?

Edit: I use Dialogs.MessageDlg(...) to display the message.

like image 302
Alois Heimer Avatar asked Nov 22 '13 11:11

Alois Heimer


3 Answers

You can filter queued messages, such as WM_TIMER, with TApplication.OnMessage.

procedure TMainForm.ApplicationMessage(var Msg: TMsg; var Handled: Boolean);
begin
  if ShowingFatalErrorDialog then
    if Msg.Message = WM_TIMER then
      Handled := True;
end;

Either assign that event handler directly to Application.OnMessage or use a TApplicationEvents object.

Obviously you'll have to provide the implementation for ShowingFatalErrorDialog but I trust that it is obvious to you how to do so.

like image 50
David Heffernan Avatar answered Nov 17 '22 10:11

David Heffernan


Try something like this:

    ...
  private
    FAboutToTerminate: Boolean;
  end;

...

type
  ESevereError = class(Exception);

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Tag := Tag + 1;
  if Tag > 2 then
    raise ESevereError.Create('Error');
end;

procedure TForm1.ApplicationEvents1Exception(Sender: TObject;
  E: Exception);
begin
  if (E is ESevereError) and (not FAboutToTerminate) then
  begin
    FAboutToTerminate := True;
    Application.ShowException(E);
    Application.Terminate;
  end;
end;
like image 35
NGLN Avatar answered Nov 17 '22 10:11

NGLN


Just for reference: I will use the following code, which is a mixture from both answers.

procedure SaveShowErrorMessage(...)
begin
    with TFatalErrorAppEvents.Create(nil) do  //avoid timer and further exceptions
    try
      Dialogs.MessageDlg(...);
    finally
      Free;
    end;
end;

With TFatalErrorAppEvents as follows:

type
    TFatalErrorAppEvents = class(TApplicationEvents)
    protected
        procedure KillTimerMessages(var Msg: tagMSG; var Handled: Boolean);
        procedure IgnoreAllExceptions(Sender: TObject; E: Exception);
    public
        constructor Create(AOwner: TComponent); override;
    end;


constructor TFatalErrorAppEvents.Create(AOwner: TComponent);
begin
    inherited;
    OnMessage := KillTimerMessages;
    OnException := IgnoreAllExceptions;
end;

procedure TFatalErrorAppEvents.IgnoreAllExceptions(Sender: TObject; E: Exception);
begin
    //in case of an Exception do nothing here to ignore the exception 
end;

procedure TFatalErrorAppEvents.KillTimerMessages(var Msg: tagMSG; var Handled: Boolean);
begin
    if (Msg.message = WM_TIMER) then
      Handled := True;
end;
like image 1
Alois Heimer Avatar answered Nov 17 '22 10:11

Alois Heimer