ShowModalについて

解決


印刷屋  2010-08-19 08:09:24  No: 39010

別の質問とダブついてすいません。

ShowModalで子フォームを開くと、子フォーム起動時にOnShowで子フォームのサイズとかをいじろうとするとエラーになり、コメントにしてしばらく放置していました。
で、直近、孫フォームをDLLで表示し返値を得るために子フォームのハンドルを渡そうとしたらやっぱりエラーが出ました。
これってやはり、親フォームに何かを握られているからなのでしょうか?


Quest  2010-08-19 10:27:07  No: 39011

いやー、ShowModalで表示した子フォームのOnShowイベントで
ScaleByを使ってフォームを拡大したりしてますが、エラーになった事はないですよ。
「OnShowで子フォームのサイズとかをいじろうとする」って
具体的にはどんな事をしてますか?


HOta  2010-08-19 15:54:11  No: 39012

子フォームがまだCreateされていないのでは?


印刷屋  2010-08-20 07:19:33  No: 39013

親フォームと子フォーム(手動生成)があり、
親側で
begin
  ChildForm := TChildForm.Create(Self);
  ChildForm.Width := 500;
  ChildForm.ShowModal
  ChildForm.Release;
end;
だとうまくいきますが、
子ChildFormのOnShowイベントで
procedure TChildForm.FormShow(Sender:TObject);
begin
  ChildForm.Width := 600;

を加えると
アドレスに対する読み込みエラーがでます。


jog  2010-08-20 08:02:11  No: 39014

>ChildForm.Width := 600;

クラスのメソッドの中で特定のインスタンスを参照してるからでしょう。

self.Width := 600;

にするか

Width := 600;

にするといいんじゃないですか。


通りすがり  2010-08-20 08:23:10  No: 39015

>procedure TChildForm.FormShow(Sender:TObject);
>begin
>  ChildForm.Width := 600;

ChildFormがなんらかの原因で、過去の物となっているのだと思います。

Releaseするのは、今回の場合、問題は有りませんが
TChildFormのOnCloseで

Action:= caFree
ChildForm:=nil; 

にしておけば Release は不要です。

nil にしておけば、間違ったアクセスの場合、IDEで変数がnilかどうか確認すればいいだけなのでデバッグも楽です。

ボタンなどにModalResultが設定されている場合、押下後に自動で閉じられ OnCloseが発生し、caFree が設定されるという流れです。
その後 ChildForm は、過去の物となりますので、値を更新しない限り使えなくなります。

TFormは、かなりメッセージが飛び、よく理解していないと、解放後に操作してしまうような場合が結構見られますので、今後いろいろ機能を実装する上で、そののようにしておいたほうが無難でしょう。

この場合、TChildFormのFormShowで自身のWidthを変更したいのだと思うので

 Width:= 600

だけでOKだと思います。

ChildForm は グローバルの var で宣言されていて
TChildFormのインスタンスが入っています。

ChildForm.Width のようにアクセスするのは、TChildForm以外の場所からChildForm を参照したい場合に利用します。

また、Sender がある場合、Sender を使ったほうが良いでしょう。
今回の場合、Sender が TChildForm 以外のインスタンスである場合は考えられないとは思いますが、TChildFormを複数作っり動的に作成する場合は、

ChildForm.〜   と書くのは値が予期しない結果となる恐れがあるため推奨されないコードだと思います。

var
  frm: TChildForm;
begin
 if not Assigned(Sender) then Exit;
 if not Sender is TChildForm then Exit;

 frm:= TChildForm( Sender);
 frm.Width:= 600;
end;

こう書くのがよろしいかと思います。

var
  frm: TChildForm;
begin
 if not Assigned(Sender) then Exit;
 try
   frm:= Sender as TChildForm;
   frm.Width:= 600; 
 except
  例外処理
 end; 
end;

こう書けば、Sender が TChildForm 出ない場合は例外が出ます。
品質、デバッグ優先なら後者のほうがお勧めです。


印刷屋  2010-08-20 08:41:14  No: 39016

早速ありがとうございます。

>>ChildForm は グローバルの var で宣言されていて
>>TChildFormのインスタンスが入っています。

この説明でようやくわかりました。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加