问题
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.
回答1:
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.
回答2:
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;
回答3:
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;
来源:https://stackoverflow.com/questions/20143875/how-to-ignore-timer-events-in-delphis-messagedlg