• ベストアンサー

[C#]FormクラスのShowメソッドの挙動について

C#のSystem.Windows.Forms.FormクラスのShowメソッドについて調べています。 Showメソッドを使うことで、モードレスでフォームを表示できます。 http://msdn2.microsoft.com/ja-jp/library/39wcs2dh.aspx 例えば、ボタンがクリックされたときに、モードレスでフォームを表示する場合は、以下のようになると思います。 // ボタンがクリックされたときにコールされるメソッド private void button1_Click(object sender, EventArgs e) { MyForm form = new MyForm(); // MyFormはFormの継承クラス form.Show(); } このとき、button1_Clickメソッドが終了しても、 つまり、変数formのスコープから処理が外れても、MyFormは表示され続けます。 別スレッドで表示しているのかと思いましたが、MyFormを表示してもスレッド数は変わりませんでした。 なぜ、変数formのスコープから処理が外れても、MyFormが表示され続けるのかわかりません。 どなたかご存知の方がいらっしゃいましたら、ご教授いただけると幸いです。 環境 : WindowsXP SP2, .NET Framework 2.0, Visual Studio 2005

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

色々ややこしい話があったと覚えている上に元ネタ失念なのですが, Formクラスの中で表示中のForm一覧みたいなコレクションを持っている, というのが理由だったと思います。 その結果,表示されているFormについては,GC対象にならず表示し続けているのだったと思います。 # 公開された,ソースコードをあたれば一発なのでしょうが……。 ちなみに,インスタンスが生存する期間は,newされてからGCされるまでです。 CloseだのDisposeだのは,Unmanaged Resourceを解放するための手段にすぎません。

その他の回答 (3)

  • isle
  • ベストアンサー率51% (77/150)
回答No.4

フレームワークは保持している参照を使って順番にフォームへイベントを通知してやるだけで良いので、メインスレッドひとつで済みます。

  • isle
  • ベストアンサー率51% (77/150)
回答No.3

Formをnewすると、自分で書いたプログラムの変数で受け取る参照とは別にフレームワークが内部で参照を持ちます。 なので変数のライフタイムが終了してもフレームワークからの参照は残り続けるので表示されたままです。 既に書かれている通りフレームワークが保持している参照はコレクションから取得できます。 Disposeはフレームワークが保持している参照を破棄させます。 Closeはフォームを閉じるだけです。 > なぜ、変数formのスコープから処理が外れても、MyFormが表示され続けるのかわかりません。 この理屈だと最初のフォームは表示されること無く(あるいは一瞬で)消えてしまうことになるかと。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

fromがnewで実体化されたインスタンス変数だからです 実体化したクラスは 明示的にCloseまたはDisposeを呼び出すまで存続します

mamorix
質問者

お礼

ご回答ありがとうございます。 なんなとくわかった気がします。 >fromがnewで実体化されたインスタンス変数だからです 失礼ですが、formはインスタンス変数ではなく、ローカル変数だと認識しております。 http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/csspec/html/vclrfcsharpspec_1_3.asp >実体化したクラスは 明示的にCloseまたはDisposeを呼び出すまで存続します なるほど。 よく考えてみると、ローカル変数formは、言わばC言語のポインタの役割しかしていないため、 それがスコープから外れる外れないに関係なく、インスタンス(=実体化したクラス)はメモリ上に残り続けるとというわけですね。 どうもありがとうございました。

関連するQ&A

  • FORM1からFORM2にパラメータの引渡し

    Public class Form1 Private Sub Button1_Click(------------------) Dim textBox1 As String textBox1 = TextBox1.Text End Sub End Class Form1でボタンをクリックし、textBox1の値を モードレスで開いたForm2にtextBox1の値を渡したい と考えていますが、参考となるサイトがなく どのように書いたらいいのかわかりません…。 メソッド(textBox1) 'FORM1側 Public Sub メソッド(ByVal textBox1 As String) ' FORM2側 で出来ると思ったのですが、この場合モードレスで開いたとしても パラメータが渡せない?と思い…。 ヒントでもいいので、アドバイスをよろしくお願いします。

  • C# Formの操作

    Form2 form2 ; // 子 Form Form3 form3 ; // 子 Form private void button1_Click(object sender, System.EventArgs e) { form2 = new Form2() ; this.AddOwnedForm(form2) ; // 親 Form が form2 を所有する form2.Show() ; } private void button2_Click(object sender, System.EventArgs e) { form3 = new Form3() ; this.AddOwnedForm(form3) ; // 親 Form が form3 を所有する form3.Show() ; } 上記のようにボタン一つに対して1つのFormに対する処理をするのではなく,ボタン1つに対して 複数のFormを処理する.つまり 例えば,Form1,2,3とあったとして,Form1のボタンを押してFrom2を開き,そこで何らかの処理を したものをForm1に反映する.または,From3のボタンを押してForm2を開きそこで何らかの処理を 行いForm3に反映する. この場合,Form1とForm3のどちらのFormのボタンが押されたか判断しないといけないと思うのですが,ここの処理がうまくいきません. どちらかのFormのボタンを押してForm2を表示し,どちらかのFormに反映させる所までは出来たのですが,両方の判断材料を入れて,どちらのFormのボタンを押されたか判断する際に,押されなかった方が「null」となりエラーになります. 下記にこの判断部分を掲載いたします.どなたかご教授よろしくお願いいたします. Form1 public int but = 0; public int butt1; public string DB; public string HDB; public Form2 f2 = null; private void mybutton1_Click(object sender, EventArgs e) { butt1 = 1; ・ ・ ・ public int Ye=0; private void button43_Click(object sender, EventArgs e) { butt1 = 0; From2 public partial class Form2 : Form { Form1 f1; Form3 f3; public Form2(Form1 f) { f1 = f; // メイン・フォームへの参照を保存 InitializeComponent(); } public Form2(Form3 f) { f3 = f; // メイン・フォームへの参照を保存 InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { #region int Pin1 = f1.butt1; int Pin3 = f3.butt3; Form3 Form1と基本的には同じです.

  • C# form

    Button _Button = (Button)sender; int but = 0; if (_Button.Name == "button1") { but = 1; } if (_Button.Name == "button2") { but = 2; } if (_Button.Name == "button3") { but = 3; }      //Form2クラスのインスタンスを作成する Form2 f2 = new Form2(this); //Form2を表示する //ここではモーダルダイアログボックスとして表示する ////オーナーウィンドウにthisを指定する //f.ShowDialog(this); //フォームが必要なくなったところで、Disposeを呼び出す f2.Show(); 上記のようにボタン配列を作成し,クリックイベントを発生させています.そこで押されたボタンにより butに所定の値を入れてこれを,form2において判断値として使用したいのですが,どのようにすれば 良いでしょうか? 昨日から悩んでいるのですが自分だけでは解らないのでご教示願いたいと思います.

  • イベントハンドラメソッドに関して教えてください

    お世話になります。イベントハンドラメソッドについて教えてください。 -----JS----- function f() { window.alert("Click"); } ---(1) document.myform.mybtn2 = function(){ ---(2) window.alert("Click"); } -----HTML----- <form id="myform" name="myform"> <input type="button" id="mybtn1" name="mybtn1" value="Click" onclick="f()" /> ---(1) <input type="button" id="mybtn2" name="mybtn2" value="Click" /> ---(2) </form> Q:上記のコードで(1)の場合だと正常にalert画面が出ますが、(2)の場合だと何も起こりません。 FirefoxのJavaScriptコンソールで調べると下記のエラーが表示されます。 documnet.myform has no propaties なぜエラーが発生するのか分からずに困っています。 解決の手がかりでもよいので教えてください。

  • 別formの多重起動防止

    どうもお世話になってます。 visual C++/CLIでプログラミングしています。 ボタン1を押したら別のフォームをモードレスで 表示させたいのですが private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { Form2^ otherform = gcnew Form2(); otherform->Show(); } このようにした場合ボタンを押すたびに次々とフォームが 多重起動していきます。これを1つだけ表示させるように したいのですが… こちらのサイト http://dobon.net/vb/dotnet/form/singleform.html の方を参考にしてC++用に書き直してみたいのですが どのように書いたらよいか教えてもらえないでしょうか? よろしくお願いします。 自分は以下のように書き直してみたんですが 大量のエラーを吐き出してしまいました。 private: static Form2^ _instance; public:  static Form2 Instance{    get     {     if (_instance == null || _instance.IsDisposed)     _instance = gcnew Form2();     return _instance;     } } private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { Form2->Instance->show(); }

  • 新しくform2を開いた時、呼び出した親のform1を最前面に表示したい。

    Form1から  Form2.Show 0, Me と、Form2を開きます。 この際、Showメソッドの書式  object.Show style, ownerform のstyleは0(モードレス)です。 この状態でデバッグモードにし、呼び出した元のForm1をクリックした時、Form1はアクティブになるのですがForm2の後ろに隠れて見えません。 Form1がForm2の後ろにあってもフォーカスが移動したら最前列に表示させることは出来ないでしょうか? ご存知の方々、どうかお知恵を貸してくださいm(_ _)m

  • 仮想メソッドをoverrideすると怪しい動作

    こんにちは。C#で仮想メソッドの勉強をしています。Form1でボタンを押すとフォームが閉じるメソッドを書きました。 Form2でoverrideしてメッセージボックスを表示するようにメソッドを再定義しました。 ここで問題なのですが、Form2でcmdCloseボタンをクリックすると「閉じます」というメッセージを表示した後に、もう一度「閉じます」というメッセージが表示されます。 2回メッセージが表示されるのが腑に落ちなく、何が原因なのかお教え頂きたく思います。よろしくお願いします。 Form1 /******************************************************************************/ // フォームクローズ /******************************************************************************/ protected virtual void cmdClose_Click(object sender, EventArgs e) { this.Close(); } Form2 /******************************************************************************/ // フォームクローズ /******************************************************************************/ protected override void cmdClose_Click(object sender, EventArgs e) { MessageBox.Show("閉じます"); }

  • 【C#】Form1からForm2を表示したとき、Form2がForm1

    【C#】Form1からForm2を表示したとき、Form2がForm1を所有する 検索しても見つからなかったので質問させていただきます。 Form1からForm2を表示(Form2.Instance.Show();)したとき、 Form2がForm1の上にこないように、また、Form2は必ずForm1のすぐ後ろであるようにして欲しいんです。 たとえば、 IEで検索ウィンドウを開いたときに、検索ウィンドウを表示していてもIEは操作できるけど(モードレス)、IEの後ろに検索ウィンドウが行くことはありません。 これはForm2.Instance.Show(this);とすればいいだけですが、 自分がやりたいのはその逆です。 検索ウィンドウの後ろにIEが行くことがないようにしたいんです。 Form1.Activateなどを使って無理やりさせようとしましたが、 無理だったので質問しました。 わかる方は教えていただけると嬉しいです。 お願いします。 (ちなみにVisualStudio2010、.NET Framework3.5です。)

  • [VB6] フォームを閉じる方法について

    お世話になります。 VB6で別フォームを起動する際の親フォームの閉じ方について 質問させてください。 呼び出し元フォームからShowメソッドで別フォームを起動すると、 呼び出し先のフォームでマウスのカーソルが砂時計表示になってしまいます。 (呼び出し元のフォームはUnload Meで閉じています。) [Form1の処理] Private Sub Button1_Click() Form2.Show Unload Me End Sub ※Form1は呼び出し元。Form2は呼び出し先。 原因について、どなたかご存知の方がいらっしゃいましたら、 ご教授願えますか?

  • C#でオブジェクトの有無を取得する

    オブジェクトが作られている時と作られていない時で処理をわけたいのですがうまくいきません。 この書き方の何がまずいのでしょうか? namespace オブジェクト検索 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Control c = Controls["form2"]; if (c != null) { ((TextBox)c).Text += "*"; } } private void button2_Click(object sender, EventArgs e) { Form2 form2 = new Form2(); form2.Show(); Application.DoEvents(); } } } ボタン2を押した時に新しいフォームが立ち上がり、そのフォームがあるときは*が出るようにしたいです。

専門家に質問してみよう