2013-11-22 11 views
5

私はDelphiでグローバル例外ハンドラを設定しました。重大な例外を除いて、エラーメッセージが表示されます(Halt()が続きます)。エラーメッセージが表示されている間、Delphiはエラーをさらに引き起こすタイマーイベントを処理しているメッセージキューを処理しています。Delphis MessageDlgでタイマーイベントを無視する方法

私が欲しいのは、タイマーイベントを処理しないエラーダイアログを表示することです。 Delphiではどのように可能ですか?

編集:私はDialogs.MessageDlg(...)を使ってメッセージを表示します。

+0

は、私はメッセージのみがそのエラーダイアログに宛てていることが通過しますので、あなたは「最終的なエラーメッセージが表示されている」とAppのOnMsgインターセプトいくつかのグローバルフラグを持つべきだと思います、他のメッセージは除外されますhttp://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Forms_TApplication_OnMessage.html –

+2

'TTimer'を使用すると、すべての'ダイアログを表示する前に 'Application'のための' TTimer'(s)を実行してください。ちょっとした考え。 – kobik

+0

@kobikその後、私のグローバル例外ハンドラはすべてのTTimerを認識する必要があります。私は他のソリューションを好む。 –

答えて

4

あなたがTApplication.OnMessageで、このようWM_TIMERとしてキューに入れられたメッセージをフィルタリングすることができます。

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

Application.OnMessageに直接そのイベントハンドラを割り当てるかTApplicationEventsオブジェクトを使用しますか。

具体的には、ShowingFatalErrorDialogの実装を提供する必要がありますが、私はそれを行う方法は明らかです。

+0

私はダイアログ内のメッセージをフィルタリングすることを考えていました。しかし、TApplicationEventsを使用すると、グローバル変数に頼ることなくこのように動作します。ありがとう。 –

+0

ブラックリストのアプローチはここでは行き止まりだと思います。 1つは、代わりにホワイトリストポリシーを実装する必要があります –

+0

@ Arioch'The私は思う質問にそのコメントを投稿するつもりだった。 –

2

はこのような何かを試してみてください:

... 
    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; 
+0

ありがとう、私はあなたの考えを最終的な実装ですべての例外を飲み込むために使用しました。しかし、私の主な焦点は、最初の行に致命的なタイマーイベントを生成しないことでした。 –

+1

あなたのコードの 'FreeAndNil(E)'部分が間違っていると思います。ドキュメントによると、私はあなたが例外を解放するはずではないと思います。これは私のための[アクセス違反](http://stackoverflow.com/q/22630972/2523663)につながります。 [この説明](http://stackoverflow.com/a/22668566/2523663)を見てください。 –

+0

ありがとう!たぶん 'ApplicationEvents.CancelDispatch'がAVを防ぐのに役立つかもしれませんが、例外を破壊しないことは確かに良い方法です! – NGLN

1

ちょうど参考のために、次のコードを使用します。これは両方の回答が混在しています。 TFatalErrorAppEventsで

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

は、次のように:

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; 
関連する問題