VB2008EEでのFormモーダレス表示とCloseボタン処理についての技術論

このQ&Aのポイント
  • VB2008EEのForm1からForm2をモーダレスで表示し、Closeボタンの処理をHideに変更する方法について説明します。
  • FormClosingイベントハンドラでHide()→e.cancel=Trueの処理を行うと、Form2のインスタンスを再利用できるが、アプリが終了しなくなる問題が発生します。
  • ShowDialog→Xボタンの後ではアプリは終了可能ですが、Show→Xボタンの後ではアプリが終了できません。そのため、このような制御を行う際は注意が必要です。
回答を見る
  • ベストアンサー

(VB2008EEです)Form1からForm2をモーダレスで表示(S

(VB2008EEです)Form1からForm2をモーダレスで表示(Show(Me))したのち、 Form2を、(Form2の)閉じるボタン(右上にあるXボタン)で閉じるときに、 単にHideするだけの処理に変更することは可能でしょうか。 デフォルトでは、閉じるボタンですと、Close()と同様、 Close(&Dispose)となると思いますが、Hide()処理に 変えられるかということです。 。。。 試しに、FormClosingイベントハンドラでHide()→e.cancel=Trueって やってみたところ、(再度同じForm2のインスタンスを使ってShowができ、 さらに前回のText表示などが残っているなど)その場はうまく行ったように 見えたのですが、そうすると、アプリ(Form1)が閉じるボタンで終了しなくなって しまいました。 (Application.Exitでもダメ、Endでは(強制終了とのことなので)OKですが) Form2のClose処理をCancelしているからだ、とは思いますが。 ShowDialog→Xボタン(同じ記述のまま) の後では、終了可能です。 では、Show→Xボタンのあとで、同じインスタンスで、上記と同じように、 ShowDialog→Xボタンとしたあと、Form1のXボタンでアプリを 終了させようとするとどうなるか。 結果は、終了不能でした。 一度Show→Xしたらそれをどこかに覚えている?ってことなのでしょうか。。。 ここらへんの現象まで、合わせて説明できる方がいらっしゃったら 合わせてご説明いただけませんでしょうか。 。。。 なお、なぜこんなことするの?という実際論はここではなしで 純粋に技術論でお願いいたします。

noname#166246
noname#166246

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

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

Form2のFormClosingのコードはどのようになっているのでしょう? Xまたはシステムメニューの閉じるの場合だけHideを実行したいなら Private Sub Form2_FormClosing( 引数省略 )   if e.CloseReason = CloseReason.UserClosing then     e.Cancel = True     me.Hide()   end if End Sub といった具合にしてみてはいかがでしょう

noname#166246
質問者

お礼

ありがとうございました。 なるほどーという感じです。

noname#166246
質問者

補足

すいません、忘れがちな自分用にメモをここに書かせてください。 「フォームが閉じられる時その原因を知る」 http://dobon.net/vb/dotnet/form/unloadmode.html 「(MSDN)CloseReason 列挙体」 http://msdn.microsoft.com/ja-jp/library/system.windows.forms.closereason.aspx

関連するQ&A

  • (VB2008)ShowDialogしたFormを閉じた時の、画面の挙

    (VB2008)ShowDialogしたFormを閉じた時の、画面の挙動について (VB2008EE、OSはVista) Form1からForm2を(ボタンのクリックイベントで) Dim f As New Form2 f.Show(Me) と記述して表示させたあと、 Form2の(ボタンのクリックイベントで) Me.Hide() として、Form2を閉じる記述を書きました。 で、Form2をShowDialogしてから、Hideを実行すると、 Form2が消えるのはいいのですが、残るForm1が、 ・デバッグ実行時は、VB2008EEのWindowの後ろに隠れてしまい、そのままとなる。 ・リリースビルドでは、さすがにそのままとはなりませんが、一旦Form1が  ちらつきます。 この回避策がありましたら教えてください。 。。。 ここからは、いろいろ実験した結果です。 ・試しに、Me.Hide()の後ろに、Threading.Thread.Sleep(5000)を 記述して実行すると5秒間Form1が後ろのアプリ画面に隠れた後、 Form1が前に表示される。 ・この場合の「後ろの別アプリのWindow」について、その別アプリが VB2008やエクスプローラだとForm2がそのアプリに隠れるのですが、 ExcelやIEだと、Form1が後ろに隠れることがないようです。。。 ・Hideではなく、Closeだと、後ろには隠れません。 (ただし、Closeの場合、Threading.Thread.Sleep(5000)の間はForm2は その前にClose()があっても、表示されたままSleepしその後閉じます) ・さらにShowDialog()でなく、Show()の場合、Owner指定して実行した場合は、 (つまりSHow(Me))全く問題なく、Form1が前面に表示されたまま 他のアプリが前に来ることはないのですが、 Ownerを指定せずにShowしたところ、ShowDialogと同様のことが起きるようです。 もし、これらの現象全体についてしっかりと説明できる方がいらっしゃれば、 説明もしていただけるとうれしいです。

  • WindowsFormの消去について(C#)

    こんにちわ。 C#(WindowsForm)で以下のような処理を考えています。 1.起動するとForm1(ログイン画面)が開く 2-1.認証に成功 → 3へ 2-2.認証に失敗 → メッセージを表示し、ログイン画面のユーザ名にフォーカスをセット 3.Form3(メインメニュー)を開く そこで、スタートアップの画面は、Form1で良いと思うのですが、 2-1の場合に、以下のようなコードを書いてみました。 *************************************** Form3 f = new Form3(); f.ShowDialog(this); f.Dispose(); this.Close(); *************************************** これでは、次の部分で目的を達成できませんでした。 A.Form3をShowDaialog(this)で開くと、モーダルモードで開くだけとなってしまう。 Showではモードレスとなるだけ。 B.Dispose、Closeを記述してみたが、Form3が開いた時に、 画面上からForm1が消えるわけではない。 Closeでは、システム自体が終了してしまう。 そこで、ShowDialogやShowではなく、Form1を消し、Form3を表示するメソッド等あるのでしょうか? ちなみに、Form3をCloseした場合に、Form1を再度呼び出す処理は考えていません。

  • Form1からShow()で表示したForm2が、CloseまたはHi

    Form1からShow()で表示したForm2が、CloseまたはHideで消えたあと、 制御が戻ってきたForm1の側で、CloseされたのかHideされたのかを 判別する手段はございますでしょうか? あればその手段を教えてください。 無理なら無理でしょうとご指摘ください。 Form2の参照変数( Dim f As Form2 の f )はCloseでも Nothingにならないので「Is Nothing」では判別できませんでした。 参照はしているけど、その参照先が破棄(解放)されているって ことですよね。 他の変数を理由するという答え以外でお願いいたします。

  • 【VB.NET2003】フォーム1を閉じてフォーム2を表示させたい

    プログラミング初心者でVB.NET2003使用です。 検索したところ、それらしいものがあったのでチャレンジしましたがダメだった(ちょっと違う?)ので質問させていただきます。 http://oshiete1.goo.ne.jp/qa1757174.html 《やりたい事》 Form1に配置したボタン1をクリックするとForm1を閉じてForm2を表示 Form2に配置したボタンAをクリックするとForm2を閉じてForm1を表示する。 これをやりたいのですが、なかなかうまく行きません。 ボタン1をクリックしてForm1を閉じないでForm2をShowかShowDialogでモードレス表示 ボタンAをクリックしてForm2をCloseさせてForm1を表示させる事(元々閉じていないので)は出来ます。 可能ならばどちらかを必ず閉じる方法でやりたいと思います。 可能でしょうか? 解決策やヒント、良いサイトがありましたら回答をお願いします。

  • C#で、ある条件でFormが自動で閉じるプログラム

    C#で、例えばForm2をForm1から開き、ある問題があってForm2のボタンを押すとForm2のラベルに正解と表示されます。 その文字が表示されたら数秒後に自動でForm2が閉じられるプログラムを書きたいのですがうまくいきません。 現在、こう書いています。3秒後とします。 using System.Threading;は宣言しています。 private void Form2_FormClosing(object sender, FormClosingEventArgs e) { if(label1.Text=="正解です。") { Thread.Sleep(3000); e.Cancel= false; } こうするといつまでも閉じてくれません。 ボタンクリックプログラムに、if文で、~ならば正解です、~ならば間違いです、などとふり分けている中、正解のところに label1.Text="正解です。"; Thread.Sleep(3000); this.Close(); などとすると、ボタンを押したら、ラベルには何も表示されずに3秒後に閉じます。 どうすればいいでしょうか?

  • CloseとDisposeの違い

    みなさまこんばんわです。よろしくお願い申し上げます。 VB.NET 2008でコーディングしています。 CloseとDisposeの違いについて教えていただきたいのです。 これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。 たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、タイマーコントロールのイベントに記述していますと、それは実行され続けます。 これを防ぐために、Me.Dispose() を使います。すると、きれいにプロセスは終了し、イベントは発生しない模様です。 そこで、「フォームを閉じる」意味のMe.Close() をすべてMe.Dispose() に変えてしまいました。確実にプロセスを破棄出来ると思ったからです。Webで調べると、違いは「再利用できる、できないの違い」という答えがありましたが、それはきっと、ファイルやオブジェクトのことで、フォームの場合は、再びShowまたはShowDialogで表示させることは可能でしたので、特に問題は感じていませんでした。 ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。Me.Close() に変えるとうまくいきました。 わけわからなくなってきました。。。 ちなみに、その残ったフォームは、スタートアップフォームであり、別のフォームからShowまたはShowDialogメソッドで呼び出したものではありません。 ここで4つの仮説を立ててみました。 1. ShowDialogで呼び出したフォームは、Me.Dispose()、Showで呼び出した、あるいは、スタートアップフォームは、Me.Close() すれば破棄できる 2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる 3. 呼び出し方ではなく、別の要因が存在する 4. 併記する必要がある場合がある Me.Close() Me.Dispose() または、 Me.Dispose() Me.Close() どれが正しいのでしょうか?どなたがご存じの方がいらっしゃいましたら、ご教授いただけませんでしょうか? どうぞよろしくお願い申し上げます。ありがとうございました。

  • showdialogを使わずにモーダル表示したい。

    VB2005環境です。 FormAから、FormBをShowしています。 FormB画面がある時は、FormAを触らせたくないので、 モーダル表示にしたいと考えているのですが、元々Showして 作っており、更にFormAがFormBのCloseイベントをハンドルして いろいろ処理を書いたせいか、原因が特定できないのですが、 ShowDialogしてcloseすると ystem.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。 とのエラーが出ます。 ShowでFormBを起動する作りのまま、FormAだけ触れないように したいのですが、Showでモーダル表示にできるような方法が ありましたら教えていただけないでしょうか? 宜しくお願いします。

  • Form オブジェクトの戻り値の設定

    はじめまして。Porome です。 Excel 2003 の VBA を使ってプログラミングをしています。 Form オブジェクトの戻り値の設定方法/受取方法について教えてください。 実装したいプログラムの概要は、以下の通りです。 標準モジュールに記載したサブルーチンから Form オブジェクトを 生成し、Form オブジェクトで入力されたデータを標準モジュール側 で取得する…というものです。 書きたいソースコードのイメージは以下の通りです。 Sub MySub1() dim i_Form As New MyForm1 dim i_Name As String dim i_Age As String dim i_Ret As Integer 'MyForm1OK, MyForm1Cancel が戻ってくるまで、じっと待つ i_Ret = i_Form.Show, vbModal Select Case i_Ret 'MyForm1 で OK ボタンが押された Case MyForm1OK: i_Name = i_Form1.txtName.Value i_Age = i_Form1.txtAge.Value MsgBox(i_Name & " さんの年齢は " & i_Age & " 歳です") 'MyForm1 で Cancel ボタンが押された Case MyForm1Cancel: MsgBox("処理はキャンセルされました") 'MyForm1 では、MyForm1 では、MyForm1OK, MyForm1Cancel 以外は '戻さない仕様とします。 Case Else '何もしない(ここには来てはいけない) End Select End Sub こういったことを実現するためには ・MyForm1 では、 OK ボタンを押したら、MyForm1OK を Show メソッドの戻り値として セットし、処理を MySub1 に戻す Cancel ボタンを押したら、MyForm1Cancel を Show メソッドの戻り値としてセットし、処理を MySub1 に戻す OK ボタン、Cancel ボタン Click 以外の Form イベントでは、MyForm1 での処理が継続され、MySub1 は MyForm1 の戻り値(MyForm1OK/MyForm1Cancel)を、じっと待つ といったことが必要になってくるかと思います。 こういった処理を実装するには、呼び出し元 (MySub1)、呼び出し先 (MyForm1) では、それぞれどのようなコードを記載すればよろしいでしょうか? 説明が下手で申し訳ありませんが、アドバイスをお願いいたします

  • 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において判断値として使用したいのですが,どのようにすれば 良いでしょうか? 昨日から悩んでいるのですが自分だけでは解らないのでご教示願いたいと思います.

  • Visual C++ 2008 EEでメッセージ表示

    Visual C++ 2008 EEを使用し、以下のコードを組みました。これは1つのフォーム(仮に質問フォームとする)に3つのボタンを作成し、ボタンを押すとそれぞれの3種類の質問項目フォームにいって、質問回答が終わったら再び質問フォームに戻ります。このとき、一度回答した質問項目のボタンは選べないようにしていて、全部の質問に答えた場合(全てのボタンが選べなくなった場合)に「これで質問は終わりです」というようなメッセージを表示したいのですが、方法が分からないのでご教授願います。 private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { this->Hide(); Sai500^ cSai500 = gcnew Sai500(); cSai500->gvflnm(this->flnm); cSai500->ShowDialog(); this->button1->Visible = false; this->Show(); } private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { this->Hide(); Sai030^ cSai030 = gcnew Sai030(); cSai030->gvflnm(this->flnm); cSai030->ShowDialog(); this->button2->Visible = false; this->Show(); } private: System::Void button3_Click(System::Object^ sender, System::EventArgs^ e) { this->Hide(); Sai040^ cSai040 = gcnew Sai040(); cSai040->gvflnm(this->flnm); cSai040->ShowDialog(); this->button3->Visible = false; this->Show(); }

専門家に質問してみよう