C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: 子フォームのイベントからフォームを閉じる


(過去ログ 63 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■36285 / inTopicNo.1)  子フォームのイベントからフォームを閉じる
  
□投稿者/ さんだ (1回)-(2009/05/26(Tue) 21:10:38)

分類:[C#] 

C#.NET2003を使用していますが、メインフォームからモーダルフォームを開いて、モーダルフォームで発生したイベント
に対して、メインフォームがある処理をしてから、メインフォームからForm2を閉じる処理をしたいのですが、どのように
記述したらよいのでしょうか?
教えてください。
//プログラムは以下のように書きましたがどのようにしたらいいのかわかりません

//メイン
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
Form2 f = new Form2();
f.BtnClick +=new EventHandler(f_BtnClick);
f.ShowDialog(this);
}
private void f_BtnClick(object sender, EventArgs e)
{
MessageBox.Show("ボタンが押されました");
//ここでForm2のフォームのみ閉じたい
}
//----Form2.cs
public event EventHandler BtnClick;
//テスト用ボタン押下時のイベント(使用完了)
protected virtual void OnBtnClick()
{
if(BtnClick != null)
BtnClick(this,null);
}
private void button1_Click(object sender, System.EventArgs e)
{
OnBtnClick();
}
引用返信 編集キー/
■36302 / inTopicNo.2)  Re[1]: 子フォームのイベントからフォームを閉じる
□投稿者/ 魔界の仮面弁士 (1084回)-(2009/05/26(Tue) 23:35:25)
2009/05/27(Wed) 00:01:53 編集(投稿者)
# おっと、2003 でしたか。
# 回答にうっかり FormClosing イベントを使っていたので、1.1 向けのコードに書き直し…。


■No36285 (さんだ さん) に返信
> private void button1_Click(object sender, System.EventArgs e)
> {
> 	Form2 f = new Form2();
> 	f.BtnClick +=new EventHandler(f_BtnClick);
> 	f.ShowDialog(this);
> }
using ブロックを使ってください。ShowDialog で開いたフォームは、Dispose せねばなりませんので。
http://msdn.microsoft.com/ja-jp/library/c7ykbedk.aspx

     using (Form2 f = new Form2())
     {
          f.BtnClick += new EventHandler(f_BtnClick);
          f.ShowDialog(this);
     }



> protected virtual void OnBtnClick()
> {
OnEventName メソッドは、EventArgs 継承クラスを引数に受け取るように実装する方が一般的かと。

> 	if(BtnClick != null)
> 		BtnClick(this,null);
> }
null を渡すべきではありません。せめて EventArgs.Empty を渡しましょう。


> どのように記述したらよいのでしょうか?
Form1 / Form2 それぞれの役割が記載されていないので、
どのように実装するのが適切かは答えにくいですが:


たとえば今のコードなら、sender に Form2 のインスタンスが入っているので、
それを使って Close する事ができます。
   // Form1 側
   ((Form2)sender).Close();


もしくは、Form2 はダイアログとして呼ばれるようなので、デザイン時にあらかじめ
Form2 上のボタンの DialogResult プロパティを設定して、閉じるためのボタンとしての役目を
持たせておき、呼び出し元の Form1 側では、ダイアログを閉じるべきかどうかを、
   // Form1 側
   f.Closing += new CancelEventHandler(f_Closing);
のイベントの引数 e.Cancel で制御するとか。

引用返信 編集キー/
■36305 / inTopicNo.3)  Re[2]: 子フォームのイベントからフォームを閉じる
□投稿者/ さんだ (2回)-(2009/05/27(Wed) 00:28:14)

> using (Form2 f = new Form2())
> {
> f.BtnClick += new EventHandler(f_BtnClick);
> f.ShowDialog(this);
> }
>> ((Form2)sender).Close();

よく参考書には、ShowDialog()で表示したのは、Dispose()で閉じると書いてありますが、
Close()でもいいのですか?


引用返信 編集キー/
■36307 / inTopicNo.4)  Re[3]: 子フォームのイベントからフォームを閉じる
□投稿者/ 魔界の仮面弁士 (1085回)-(2009/05/27(Wed) 01:19:41)
No36305 (さんだ さん) に返信
>> using (Form2 f = new Form2())
>> {
>> f.BtnClick += new EventHandler(f_BtnClick);
>> f.ShowDialog(this);
>> }
> >> ((Form2)sender).Close();
> よく参考書には、ShowDialog()で表示したのは、Dispose()で閉じると書いてありますが、

その通りです( No36285 には、Dispose が書かれていませんでしたよね)。
そしてその IDisposable.Dispose 呼び出しを保証するために、using を使うわけです。
http://msdn.microsoft.com/ja-jp/library/yh598w02.aspx


> Close()でもいいのですか?

いいえ。Dispose と Close では、それぞれの役割が異なります。

ダイアログとして呼び出されたフォームは、Close しても単に非表示になるだけで、
インスタンスとしては残っています。そのため、Dispose で後始末をする必要があります。
このことは、前回 No36302 で紹介した URL にも若干の解説がありますので、
下記の Close メソッドの説明と併せて読んでおいてください。
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.form.close.aspx
引用返信 編集キー/
■36313 / inTopicNo.5)  Re[4]: 子フォームのイベントからフォームを閉じる
□投稿者/ 渋木宏明(ひどり) (1162回)-(2009/05/27(Wed) 09:27:03)
渋木宏明(ひどり) さんの Web サイト
>>よく参考書には、ShowDialog()で表示したのは、Dispose()で閉じると書いてありますが、
>
> その通りです( No36285 には、Dispose が書かれていませんでしたよね)。

違うと思う。

ShowDialog() で表示した Form に対する Dispose() は「Form クラスが内包する Win32 ダイアログのハンドル破棄を促している」のであって、「閉じる」しているのではない。

「閉じる」という点に注目するのであれば、ShowDialog() を抜けてきた時点で、ダイアログはユーザ操作によって既に閉じています。



引用返信 編集キー/
■36314 / inTopicNo.6)  Re[4]: 子フォームのイベントからフォームを閉じる
□投稿者/ 渋木宏明(ひどり) (1163回)-(2009/05/27(Wed) 09:39:27)
渋木宏明(ひどり) さんの Web サイト
2009/05/27(Wed) 09:40:15 編集(投稿者)

> ダイアログとして呼び出されたフォームは、Close しても単に非表示になるだけで、

Spy++ で見たら、ShowDialog() した Form を閉じると、Win32 ウィンドウとしての実体はなくなってました。

2度3度 ShowDialog() した時に内部でウィンドウハンドルがどう管理されているかまでは調べてませんが、ShowDialog() によって表示された(見掛け上の)ダイアログがユーザ操作によって「閉じた」時、非表示になっているだけではないようです。

引用返信 編集キー/
■36316 / inTopicNo.7)  Re[5]: 子フォームのイベントからフォームを閉じる
□投稿者/ 魔界の仮面弁士 (1087回)-(2009/05/27(Wed) 13:03:51)
2009/05/27(Wed) 15:02:37 編集(投稿者)

# 誤記修正:再生性 → 再生成

本題の「ダイアログを呼び出し側フォームから閉じたい」という話から、微妙に脱線してきたかも。


No36313 (渋木宏明(ひどり) さん) に返信
>>> よく参考書には、ShowDialog()で表示したのは、Dispose()で閉じると書いてありますが、
>> その通りです( No36285 には、Dispose が書かれていませんでしたよね)。
> 違うと思う。
違う? いや、本当に No36285 に Dispose は書かれていませんでしたよ? とボケてみるのは無しにして。

これは、Dispose()で閉じるわけでは無い、という意味でしょうか。


> 「閉じる」しているのではない。
ダイアログを Dispose すると、フォームは閉じ、破棄されたかと思います。
まぁ、閉じることを目的に Dispose を呼ぶ訳では無いですけれども。


> 「閉じる」という点に注目するのであれば、ShowDialog() を抜けてきた時点で、
> ダイアログはユーザ操作によって既に閉じています。
同意はできますが、今回の流れでその表現を用いてしまうと、「閉じる」という言葉の指す範囲に
幅があることなどから、先の MSDN サイトの解説とぶれてしまう気がします。


まず、ShowDialog() を抜けたからといって、それがユーザー操作によって閉じられたとは
限らないはずです。Hide()、Close()、Visible = false など、ユーザーからの操作以外でも、
ShowDialog() を抜ける可能性がありえますから。

そして先の MSDN サイトの表現では、「Close メソッドで閉じられることはない」あるいは
「(右上 X ボタンは)フォームを非表示にする」という説明の仕方が行われています。

つまり、ユーザー操作にしても、Close メソッドを使った場合にしても ShowDialog は抜けますが、
少なくとも今回紹介した MSDN 上の記述に従って言えば、
> ダイアログはユーザ操作によって既に閉じています。
ではなく、むしろ閉じられていない状態にある、と解説されていると認識しています。
(ゆえに、不要になった時点で Dispsoe を呼ぶ必要がある、と加えて説明されていますね)

http://msdn.microsoft.com/ja-jp/library/c7ykbedk.aspx
≫フォームがモーダル ダイアログ ボックスとして表示されている場合、閉じるボタン
≫(フォームの右上隅の X が付いているボタン) をクリックするとフォームが非表示になり、
≫DialogResult プロパティが DialogResult.Cancel に設定されます。
(中略)
≫ダイアログ ボックスとして表示されているフォームは Close メソッドで
≫閉じられることはないため、フォームがアプリケーションで不要になった場合は、
≫そのフォームの Dispose メソッドを呼び出す必要があります。


で、ここで MSDN に書かれている「非表示」とは、必ずしも Win32/Win64 上の話を
指しているのでは無いと私は読み取りました。Win32 の世界では、ウィンドウの再生成が
行われることになるかも知れませんが、.NET の世界では、フォームのインスタンスを
再生成することなく、続けて再表示できるという意味を指している、と。

ユーザーがフォーム右上の「×」で閉じた場合、アンマネージの世界では、実際には
ウィンドウが再生成されており、Handle も新たな HWND を返す事になりますが、
マネージの部分(Label や TextBox の表示、あるいはプロパティの中身など)は
再表示しても以前の値を復元するため、MSDN の解説はそのことを指して、
(見た目上は)非表示として扱われる仕様である、と示しているのだと思います。
引用返信 編集キー/
■36320 / inTopicNo.8)  Re[6]: 子フォームのイベントからフォームを閉じる
□投稿者/ 渋木宏明(ひどり) (1164回)-(2009/05/27(Wed) 13:37:30)
渋木宏明(ひどり) さんの Web サイト
2009/05/27(Wed) 14:38:06 編集(投稿者)

> >> その通りです( No36285 には、Dispose が書かれていませんでしたよね)。
>>違うと思う。
> 違う? いや、本当に No36285 に Dispose は書かれていませんでしたよ? とボケてみるのは無しにして。
>
> これは、Dispose()で閉じるわけでは無い、という意味でしょうか。

そうです。

> > 「閉じる」という点に注目するのであれば、ShowDialog() を抜けてきた時点で、
> > ダイアログはユーザ操作によって既に閉じています。
> 同意はできますが、今回の流れでその表現を用いてしまうと、「閉じる」という言葉の指す範囲に
> 幅があることなどから、先の MSDN サイトの解説とぶれてしまう気がします。
(略)
> マネージの部分(Label や TextBox の表示、あるいはプロパティの中身など)は
> 再表示しても以前の値を復元するため、MSDN の解説はそのことを指して、
> (見た目上は)非表示として扱われる仕様である、と示しているのだと思います。

ヘルプでそういう流れで説明されてるなら仕方ないですね。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -