メインフォームのタイマイベントにて、ある時間がきたら
メインフォーム以外の全てのウィンドウを閉じて、
実行中のモーダルフォームを表示させたいのですがうまくいきません。
よい方法はないでしょうか?
ちなみに以下の方法ではフォームが閉じずに実行中のモーダルフォームが
表示されます。
(メインフォーム、子フォームの親は全てApplication)
for i:=0 to Application.ComponentCount-1 do
begin
if Application.Components[i] is TForm then
begin
if Application.Components[i] <> MainForm then
begin
Application.Components[i] as TForm).Close;
end;
end;
end;
JikkouchuuForm := TJikkouchuuForm.Create(Application);
JikkouchuuForm.ShowModal;
JikkouchuuForm.Free;
普通は Screen.FormCount と Screen.Forms を使いますけど
なるほど、Screen変数を使うと簡単にできるんですね。
勉強になります。
さて本題のフォームが閉じない現象はなぜなのでしょう?
ループで全部閉じた後、フォームを表示しているつもり
なのですが、閉じずに残ったまま、その上にフォームを
表示してしまいます。
ちなみに実行中のモーダルフォームを閉じるタイミングで
下に残っていたフォームも閉じます。
よろしくお願いします。
uses
Unit2;
procedure TForm1.Button1Click(Sender: TObject);
begin
with TForm2.Create(Application) do Show;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i:integer;
begin
for i := 0 to Screen.FormCount-1 do
if Screen.Forms[i] <> Application.MainForm then
Screen.Forms[i].Close;
ShowMessage('ModalForm');
end;
こんなコードで Button1 を何回か押して Form2 を複数つくっておいてから
Button2 を押すとD6では期待通りになりますけど
ご回答ありがとうございます。
jokさんの回答どおりで確かに、メイン以外のフォームが消えて
別のモーダルフォームの表示ができました。
しかし、私がわからないのは、モーダルフォームをいくつか
開いておいて、ある時間(タイマイベント)がきたときに
メインフォーム以外のモーダルフォームを閉じて別のモーダルフォーム
を開くということです。
jokさんの回答に処理をあてはめてみましたが、あらかじめ表示していた
モーダルフォームが消えずにShowMessageが表示されました。
なぜなのでしょうか?
説明不足で申し訳ありませんでしたが、再度ご回答いただければ
ありがたく思います。
>しかし、私がわからないのは、モーダルフォームをいくつか開いておいて、
一つ ShowModal したら、そこでプログラムが止まるのでは?
どのように複数のモーダルフォームを開いているのかなど、最低限のソースでも
示して質問しないと…
申し訳ありません。
以下に簡単なソースを示します。
// メインフォームボタンクリック
procedure TForm1.Button1Click(Sender: TObject);
begin
with TForm2.Create(Application) do
begin
ShowModal;
Free;
end;
end;
// メインフォームタイマイベント(5sec間隔にプロパティ設定)
procedure TForm1.Timer1Timer(Sender: TObject);
var
i: Integer;
begin
for i:=0 to Screen.FormCount-1 do
begin
if Screen.Forms[i] <> Application.MainForm then
begin
Screen.Forms[i].Close;
end;
end;
with TForm3.Create(Application) do
begin
ShowModal;
Free;
end;
Timer1.Enabled := False;
end;
Button1クリックでForm2を開いておいて、5sec後のタイマイベントにて
Form2を閉じてForm3を表示したい、といった感じです。
しかし、上記ソースでは5sec後のタイマイベントにてForm2を閉じることなく
Form2の上にForm3が開き、Form3を閉じた時にForm2が一緒に閉じられます。
仮にForm2をモードレスフォームとして開いた場合は問題なく動作します。
モーダルフォームの場合はまずいのでしょうか?
よろしくお願いします。
Timer1のEnabledの使い方が間違っています。
[ヒント]
ダミーでいいので Timer1関数の最初にif i=0 then ; をかいて
ブレークポイントを関数の最初においてみましょう。
もう一つ
Screen.Forms[i].Close;
を
Screen.Forms[i].Hide;
Screen.Forms[i].Close;
にするか
本気で消すきがあるのなら、
with TForm2.Create(Application) do
begin
ShowModal;
Free;
end;
からFreeを排除して
with TForm2.Create(Application) do
begin
ShowModal;
end;
にして、
for i:=Screen.FormCount-1 downto 0 do
begin
if Screen.Forms[i] <> Application.MainForm then
begin
Screen.Forms[i].Free;
end;
にかえればいいこと
以上。
// メインフォームタイマイベント(5sec間隔にプロパティ設定)
イベントがあったときにonにして5sec間隔でタイマー稼働させたいのか
5sec後に実行して止めるのかはっきりかきましょう。
それによって
コードが大きく変わります。
Screen.Forms[i].Hide;
Screen.Forms[i].Close;
の方向でいったらどうでしょ
1回のタイマーイベント中で、Closeと次のフォーム(TForm3)のShowModalを行うとだめみたいですね。
複数のイベントで別々に処理すればOKです。
最初のイベントでCloseだけを行い次のイベントでShowModalを行うというように。
ようは1回のメッセージループでは処理できないということ。
タイマ1のイベントの中でWM_USER+???等のメッセージを投げて処理するか、
テスト的に簡単に行うならタイマ2を用意してインターバルを1に設定する。
タイマ1のイベント中でCloseを行いタイマ2を起動する。
タイマ2の中でShowModalを行う・・・
jok様、しょーとかっと様、。様、kkk様、ありがとうござます。
。様の
>Screen.Forms[i].Hide;
>Screen.Forms[i].Close;
の方向で進めていこうと思います。
タイマイベントについてサンプルでは、アプリ起動後5秒後にイベントが
発生して、Button1にて開いたForm2を消して、Form3を開くといった単純な
ものを書いたつもりでしたが、確かにEnabledが変でまぎらわしかったですね。
申し訳ありません。
kkk様のおっしゃるとおり、1回のタイマイベント中でCloseと次のフォームの
ShowModalはだめみたいですね。ただ、Closeするフォームがモードレスならば
問題なく消えたので、その点がよくわからないです。
見た目だけの問題なのであまり複雑にしたくなかったので。様の方法を選択しま
した。
ありがとうございました。
ツイート | ![]() |