皆さんこんにちは。
OnResizeイベントの発生時期に関してなのですが、
下記に様な2つのフォームがあり(TForm2にはTMainMenuが追加されています)、
1.Form1のButton1Click()によって、TForm2のインスタンスの生成及びShowメソッドを呼び出す。
2.Form1のButton2Click()により、TForm2のインスタンス破棄を行う。
とした場合、TForm2のOnDestroyイベントの発生の後に、TForm2のOnResizeイベントが発生します。
ところが、TForm2にあるTMainMenu削除すると、上記を同じ手順で行っても
TForm2のインスタンス破棄した場合に、TForm2のOnDestroyイベントのみが発生します。
こちらの動きが正常だと思うのですが、TMainMenuの有る無しでこのような動きの違いが
発生するものなのでしょうか? それとも、私の環境だけの特殊な動きなのでしょうか?
環境は、Window's 2000 SP1、Delphi7です。
-----------------------------------------------------------------------------------------------
Unit1.pas
procedure TForm1.Button1Click(Sender: TObject);
begin
MyForm2 := TForm2.Create(self);
MyForm2.Show;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
MyForm2.Free;
end;
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
Unit2.pas
procedure TForm2.FormResize(Sender: TObject);
begin
ShowMessage('resize');
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
ShowMessage('destroy');
end;
-----------------------------------------------------------------------------------------------
そういう使用だと思います。(確認しました)
で、
procedure TForm2.FormDestroy(Sender: TObject);
begin
Self.OnResize := nil; //ココを追加
ShowMessage('destroy');
end;
で、Destory時にResizeのイベントを起こさないようにできます。
@っしー
すいません誤字です。
(誤)そういう使用
(正)そういう仕様
@っしーさん、ありがとうございます。
とりあえず教えていただいた方法で解決なのですが、よろしければもう少し教えてください。
勘違いしているのかもしれませんが、私はOnDestroyが実行されたら、
インスタンスはもう破棄されているものと思っていました。
しかし、OnDestroy実行の後にOnResizeイベントが起こるということは、
OnDestroyイベントが実行された後にも、インスタンスは生きているということでしょうか?
(まあ、OnResizeイベントが実行されるということは、生きているということなのでしょうが、いまいち釈然としないもので。)
また、じゃあインスタンスはいつ破棄されるのでしょうか。
あんまり詳しくないので恐縮なのですが、、、
今回の場合は、Form2にMainMenuがあるので、Form2のDestroy時に、MainMenuが破棄されて、結果、フォームサイズが変わったということではないでしょうか?
Form1にボタンを追加して、Form2(MyForm)がインスタンス化されているかどうか、チェックしてみてはどうでしょう?
procedure TForm1.Button3Click(Sender: TObject);
begin
if Assigned(MyForm2) then
ShowMessage('インスタンス化されています')
else
ShowMessage('インスタンス化されていません');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
MyForm2.Free;
MyForm2 := nil; //この行も追加しました。
end;
>Form1にボタンを追加して、Form2(MyForm)がインスタンス化されているかどうか、チェックしてみてはどうでしょう?
を行うと、「インスタンス化されていません」と表示されます。
ただ、MyForm2はインスタンスへの参照を保持しているだけなので、
インスタンスが有効かどうかは無関係だと思います。
また、Assinged関数は、その変数がnilかどうかだけを調べるようなので、
procedure TForm1.Button2Click(Sender: TObject);
begin
// MyForm2.Free; <-削除
MyForm2 := nil;
end;
として、Button2をクリックした後、Button3をクリックしても、
「インスタンス化されていません」と表示されます。
(MyForm2がnilなので)
しかし、当然Form2のインスタンスは有効です。
ただし、MyForm2はnilなので2度とForm1からMyForm2には
アクセスできませんが。
Button2クリックを以下のように変更して実行した後、
procedure TForm1.Button2Click(Sender: TObject);
begin
MyForm2.Free;
// MyForm2 := nil; コメントアウト
end;
新たな下記のButton4のクリックを実行すると例外が発生するので、
MyForm2のインスタンスが無効であるのは間違いないようです。
procedure TForm1.Button4Click(Sender: TObject);
begin
MyForm2.Show;
end;
だから、OnDestroyイベントを実行した後からインスタンスを破棄する処理の間に、
割り込み?のような形で、OnResizeイベントが実行されてしまっているんですよね。
(詳しい動きがわからず、現象から推測しているだけなんですが)
では、下記コードで試してみてください。
MyForm2の宣言部分がミソだと思います。
今回のコードは、既にMyForm2が生成されているときは、Showのみ実行します。
//-------------------------------------------------------------------
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.dfm}
var
MyForm2: TForm2;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption := '生成・表示';
Button2.Caption := '破棄';
Button3.Caption := '確認';
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if not Assigned(MyForm2) then
MyForm2 := TForm2.Create(self);
MyForm2.Show;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
MyForm2.Free;
MyForm2 := nil;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
if Assigned(MyForm2) then
ShowMessage('インスタンス化されています')
else
ShowMessage('インスタンス化されていません');
end;
end.
すいません。ちょっと私が混乱してきたので確認させてください。
私の
「また、じゃあインスタンスはいつ破棄されるのでしょうか。」
という質問に対して、
@っしーさんが
「Form1にボタンを追加して、Form2(MyForm)がインスタンス化されているかどうか、チェックしてみてはどうでしょう?」
とアドバイス頂きました。
その後私が、
「MyForm2にAssignedを適用して判断しても、Form2(MyForm)がインスタンス化されているかどうかとは無関係に思います」
との旨の発言をしました。
そして、@っしーさんから
<では、下記コードで試してみてください。
<MyForm2の宣言部分がミソだと思います。
<今回のコードは、既にMyForm2が生成されているときは、Showのみ実行します。
と言われましたが、下記のコードを見てもMyForm2がnilなら、ただ新たにインスタンスを生成しているようにしか
見えません。
私は何か大きく勘違いしているのでしょうか?
procedure TForm1.Button1Click(Sender: TObject);
begin
if not Assigned(MyForm2) then
MyForm2 := TForm2.Create(self);
MyForm2.Show;
end;
※わたしも混乱してきました。(汗
>と言われましたが、下記のコードを見てもMyForm2がnilなら、ただ新たにインス>タンスを生成しているようにしか
>見えません。
>私は何か大きく勘違いしているのでしょうか?
その通りだと思いますが、、、
Form1からForm2を継承したフォームを幾つも生成させるには、自前で管理する機構を作る必要があるのではないのでしょうか?
説明不足で申し訳ございません。m(__)m
先に示した例は、Form1からForm2を継承したMyForm2の1つのみの例です。
もし、Delphi7ProまたはEntをお使いであれば、マニュアルの「フォームの使い方」にある「ウィンドのようなモードなしフォームを作成する」の項目を参照してください。
その項目の最後には、
『(略)アプリケーションがフォームの追加インスタンスを必要とする場合は、各インスタンスごとに別のグローバル変数を宣言します。』
と記述されています。