MDIアプリケーションにおいて単一フォームを作るには

解決


電解コンデンサ  2004-03-19 18:09:30  No: 7746  IP: [192.*.*.*]

MDIアプリケーションを作っています。
その中で、Dialogでなく、MDIChildフォームで1個しか生成しない単一フォームを作りたいのです。

//単一フォームCreate
if not Assigned(SingleForm) then
    SingleForm := TSingleForm.Create(Application);
SingleForm.Show;

そして、このフォームのCloseイベントで、
Action := caFree;
SingleForm := nil;

としました。しかし、1個しか生成しないのは良かったのですが、1回閉じてまた開く時にエラーが発生してしまうのです。
どうもSingleFormがnilになってないようで…

もし良いアドバイスをいただける方がおられましたら、どうかよろしくお願いします。

編集    削除
ふぐちゃん  2004-03-19 18:45:38  No: 7747  IP: [192.*.*.*]

具体的にどんなエラーなのかわかりませんので、
間違っているかもわかりませんが、
SingleForm := nil;
をOnDestroyに記述してみてはいかがでしょう。
私はいつもそうしているのですが、これでエラーに
なったことはないようです。

編集    削除
にしの  2004-03-19 18:55:56  No: 7748  IP: [192.*.*.*]

こちらでは出来てます。
他に原因はありませんか?
バージョンが問題かも。
こちらはDelphi7Proです。
質問時には、環境を書いた方が早く解決できることが多いです。

また、現象を、最小のソースで再現できるか確認してみてください。

編集    削除
にしの  2004-03-19 18:57:14  No: 7749  IP: [192.*.*.*]

「このフォーム」って、MDIChildの事ですよね?
まさかとは思いますが。
もちろん、MDI親フォームのOnCloseではダメです。

編集    削除
電解コンデンサ  2004-03-19 18:58:03  No: 7750  IP: [192.*.*.*]

ふぐちゃんさん、回答ありがとうございます。

ご指摘の通りOnDestroyイベントに記述したのですが、やはりエラーが出てしまいました。
エラーは、EAccessViolationです。
1回閉じて、2回目にフォームを開くコードに入った時、SingleFormがnilになっていないみたいで、Create文に入らすShowしてしまってます。

エラーになったことは無いのですか…もっと違うバグがあるのかな?

編集    削除
電解コンデンサ  2004-03-19 19:04:41  No: 7751  IP: [192.*.*.*]

にしのさん、回答ありがとうございます。

バージョンは、にしのさんと全く同じです。
記述しているのはもちろん、MDIChild側のOnCloseイベントです。

>また、現象を、最小のソースで再現できるか確認してみてください。

これをよく怠るんです…今からやってみます。アドバイスありがとうございました。

編集    削除
電解コンデンサ  2004-03-19 19:19:59  No: 7752  IP: [192.*.*.*]

にしのさんへ

今、作ってやってみたのですが、自分のはやはり2回目に開く時にエラーになってしまいます…
しかし、今度はAbstractエラーと出ました。

自分の弱い頭では原因が見当たらないです…

編集    削除
jok  2004-03-19 20:13:21  No: 7753  IP: [192.*.*.*]

> if not Assigned(SingleForm) then

これを使わずに、親フォームの  MDIChildCount と MDIChildren[] をつかって
is 演算子で TSingleForm クラスが生きているかどうかを確認すると nil を
代入する必要が無くなるのでよいと思います。

編集    削除
電解コンデンサ  2004-03-19 20:39:41  No: 7754  IP: [192.*.*.*]

以下のようにしたらうまくいきました。

unit Unit1;

    ・
    ・
    ・

type
  TForm1 = class(TForm)
    ・
    ・
    ・

  public
    procedure SingleFormNil;
end;

var
  Form1: TForm1;
  SingleForm: TSingleForm;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
    if not Assigned(SingleForm) then
        SingleForm := TSingleForm.Create(Application);

    SingleForm.Show;
end;

procedure TForm1.SingleFormNil;
begin
    SingleForm := nil;
end;

end.


そして、SingleFormのDestroyイベントで、SingleFormNilを実行しました。

書きながら思ったのですが、変数名をUnit1とUnit2で同じにしたのがマズかったのでしょうか…?

編集    削除
にしの  2004-03-19 21:17:58  No: 7755  IP: [192.*.*.*]

名前空間を使わない場合、
unit1のSingleFormは、unit1.SingleForm
unit2のSingleFormは、unit2.SingleForm
を指定したことになります。
たぶん、unit2側で、unit1.SingleForm := nil;とすれば動きますよ。

編集    削除
jok  2004-03-19 22:06:26  No: 7756  IP: [192.*.*.*]

およよー

インスタンス変数の可視性の問題だったのですね?
unit2 の TSingleForm でデフォルトで宣言されているのを使うべきだと思いますよ。
二つあれば混乱するのは当たり前です。

編集    削除
電解コンデンサ  2004-03-19 22:55:03  No: 7757  IP: [192.*.*.*]

jokさん

言われる通りです。unit1でもなぜかTSingleFormの変数宣言してるのがマズかったです。
基本がなってませんね、はぁ・・・

編集    削除