今回はDelphi/400で呼び出されたフォーム側で、
モーダルの状態を判断するテクニックをご紹介いたします。
Delphi/400では複数画面のアプリケーションを作成する場合、
標準的なフォームの呼び出し方法ではShowまたはShowModalのメソッドを使います。
この2つの違いは次の通りです。
①Show :モードレスなフォームの表示
②ShowModal:モーダルなフォームの表示
①の場合、呼び出し先フォームを開いた後も、呼び出し元フォームと切替ができますが、
②では呼び出し元フォームに切り替えることはできません。
その代わり、②では次のフォームを閉じるまで呼び出し元フォームで処理を待つことができます。
また呼び出し先フォームの解放についても、手法に違いがあります。
①では、呼び出されたフォーム自身で破棄を行います。
// 例)呼び出し先フォームのCloseイベント
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree; // クローズ時に破棄
end;
②では、呼び出し先フォームを閉じた後に、
呼び出し元フォームで破棄します。
// 例)呼び出し元フォームの呼出イベント
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2 := TForm2.Create(Application);
try
if (Form2.ShowModal = mrOK) then //【※1】(下記参照)
begin
ShowMessage('Form2をOKで閉じました。');
end;
finally
Form2.Free; // 破棄
end
end;
//【※1】呼び出し先からの結果をデバッグで確認したい場合、以下のように分けることも可能
Form2.ShowModal;
if (Form2.ModalResult = mrOK) then
begin
ShowMessage('Form2をOKで閉じました。');
end;
また②の場合、呼び出し先フォームでModalResultプロパティが設定されると、
処理終了時にそのModalResultを持って画面が閉じられます。
(ModalResultを設定せずにただフォームを閉じた場合、mrCancelが返されます。)
①の場合はModalResultプロパティを設定しても何も起こりません。
// 例)呼び出し先でOKボタン押下時
procedure TForm1.ButtonOKClick(Sender: TObject);
begin
// Closeはモーダルの場合は必須ではないが、
// 明示的に書く場合はModalResult設定より先に行う(Closeは内部的にmrCancelがセットされる)
Self.Close;
// mrNone以外の結果をセットするだけで、モーダルなら処理後に閉じられる
Self.ModalResult := mrOk;
end;
このように呼び出され方によって扱いも異なりますので、
呼び出し先フォーム側でこれを考慮する場合には、モーダル状態の把握が必要になります。
モーダル状態はフォームのFormStateプロパティで次のように判断できます。
例)ShowModalで呼び出されたかを判断
if fsmodal in Form2.FormState then
begin
ShowMessage('ShowModalで開かれています');
end;
最初にロジックを例示した呼び出し先フォームのCloseイベントも、
ShowModalで開いていた場合はクローズ時に解放してしまうと
呼び出し元画面で結果を参照できずエラーになるため、
①Show・②ShowModal の呼び分けが必要な場合は以下のような条件分岐が必要です。
(太字下線の部分を追加)
// 例)呼び出し先フォームのCloseイベント【修正版】
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if not(fsmodal in Form2.FormState) then // モーダル状態でない場合のみ
begin
Action := caFree; // クローズ時に破棄
end;
end;
汎用的な共通画面などを作る場合に有効なテクニックですので、
呼び出し元の処理を考慮してご活用ください。
(ミガロ.情報マガジン「MIGARO News!!」Vol.198 2017年5月号より)