フォームが一緒に閉じられてしまうのを回避するには?【.NET】

解決


π+  2004-09-29 02:04:03  No: 116585

たびたびすみません><
Form1でボタンをクリックしたときに、
Form2を呼び出してから、
Form1を閉じたいのですが、下記のコードだと呼び出したForm2も一緒に閉じられてしまいます。
Public Form1_form as New Form1()
public Form2_form as New Form2()

ボタンを押したとき
Form2_form.show()
form1_form.close()

順番を変えても同時に消されてしまうのですがどうしたらよいのでしょうか><


特攻隊長まるるう  2004-09-29 02:54:13  No: 116586

[VB.NET]では[VB6.0]と違って Form1 とかいうフォーム名を
記述しても対象のフォームの"実体"をグローバルに指しません。
必ず参照変数を用意してそこに新しく New するなどして実体化
したオブジェクトの参照を格納します。参照が全て開放されて
しまうとフォームオブジェクトは開放されてしまいます。この
コードと質問内容から想像するに、変数を宣言する場所と宣言の
解釈に色々と問題がありそうです。『New』や『インスタンス』
という言葉について学んで下さい。

Form2 の参照変数
>public Form2_form as New Form2()
を Form1 のクラス内で宣言していませんか?
>form1_form.close()
すると form1_form として実体化していた Form1 のクラスが
破棄・開放され、当然その中で使われていた変数は全て破棄・
開放されます。Form2_form も開放されます。

プログラムの起動時の設定はどうなっているのでしょうか?
Form1 起動なら Form2 に制御を渡して自分が消えてしまう
ようなプログラムは開放されない変数(Form など)が残る可能性
がありそうで、あまり良くないですね。

1つの方法として、Form1 の閉じる処理で処理をキャンセルし、
非表示にする事で回避できると思います。ただし、非表示にした
Form1 をプログラムを終了したい時に閉じないと、これまた終了
しないプログラムになってしまいます。

ボクが勧めるのは全体を制御する親クラスを別に用意し、Sub Main 
起動で親のクラスから Form1 を表示、Form1 のボタン押下で親クラスに
通知して Form1 は閉じて開放。親クラスが Form2 を表示するような
設計です。ご検討下さい。

過去ログ『別フォーム』などで検索しても似たような質問が
引っかかると思います。一度、目を通してみてください。


π+  2004-09-29 04:30:54  No: 116587

特攻隊長まるるうさん始めまして。ありがとうございます><
変数を宣言したのはモジュールです;;
非表示にしてから別フォームで消すのもうまくいかなかったんです。。
親クラスを別に用意したいのですが、どのようにするかいま調べてる状態です><アドバイスどうもありがとうございました!


特攻隊長まるるう  2004-09-29 09:55:43  No: 116588

Module 宣言のヘルプ読んで下さいな。インスタンスを生成できない
と書いてあると思います。つまり form1_form をクローズしてしまった
時点でインスタンスを生成している(実体化している)オブジェクトが
1つも無くなってアプリケーションが終了してるんだと思います。
親クラスを作る事で有効なオブジェクトを保持して下さい。回避できる
ようになると思います。
>非表示にしてから別フォームで消すのもうまくいかなかったんです。
それは方法が間違ってるだけです。その方法でも解決できます。


π  2004-09-29 23:52:01  No: 116589

こんにちは!ありがとうございます><!!

Class1の中に
 Public Form1_form As New Form1()
としました><

Module内では、
 Public Fshow as New Class1()
としまして、

呼び出すForm2内で
Fshow.Form1_form.show()
me.close()
としたのですが、やはり同じ結果でした><
んーもうちょっとしらべてみます><いろいろ本当にごめんなさいです・・!


特攻隊長まるるう  2004-09-30 01:13:59  No: 116590

テストプログラム作ってみました…
フォームの非表示を使わないとちょっと面倒かもしれない
事に気付きました。…が、コード的にはそんなに難しくなく
実現できました…色々な方法がありそうですが…
…公開した方がいいですか?もう少し待った方がいいですか?

終了条件を満たすまでループしつつ…って感じで作りました。
プログラムが終了してしまわないようにしないといけませんね。


π  2004-09-30 06:36:09  No: 116591

こんばんは、いろいろ試しましたがうまくいきませんでした・・・・。
スタートアップに指定したフォームは実体化されてないからクラスからcloseできないんですね。

是非、公開していただけないでしょうか・・よろしくおねがいします。。


特攻隊長まるるう  2004-09-30 17:59:30  No: 116592

' [使用コントロール] Form1・Form2 にそれぞれ Button1 配置
' [スタートアップの設定] Sub Main
' 仕様:プログラム起動で Form1 が表示されます。ボタン押下で
'Form2 表示後、Form1 は閉じます。Form2 のボタン押下で Form1
'表示後 Form2 が閉じるトグル処理が続きます。プログラムを終了
'したい場合はフォームの[閉じるボタン(×ボタン)]でフォームを
'閉じて下さい。

[VB.NET]
'/////////////////////////
Option Explicit On 
'/////////////////////////
'/// Module1.vb
'/////////////////////////
Module Module1
    Public Sub Main()
        Dim wStartClass As New Class1
        Call wStartClass.Start()
    End Sub
End Module

'/////////////////////////
Option Explicit On 
'/////////////////////////
'/// Class1.vb
'/////////////////////////
Public Class Class1
    Private Form1_form As Form1
    Private Form2_form As Form2

    Friend Sub Start()
        Call Me.ShowForm1()

        Do
            Application.DoEvents()
            System.Threading.Thread.Sleep(100)
            If Me.Form1_form Is Nothing _
            AndAlso Me.Form2_form Is Nothing Then
                Exit Do
            End If
        Loop
    End Sub

    Friend Sub ShowForm1()
        If Me.Form1_form Is Nothing Then
            Me.Form1_form = New Form1(Me)
        End If
        Me.Form1_form.Show()
    End Sub

    Friend Sub ShowForm2()
        If Me.Form2_form Is Nothing Then
            Me.Form2_form = New Form2(Me)
        End If
        Me.Form2_form.Show()
    End Sub

    Friend Sub SetForm1Nothing()
        Me.Form1_form = Nothing
    End Sub

    Friend Sub SetForm2Nothing()
        Me.Form2_form = Nothing
    End Sub

End Class

'/////////////////////////
Option Explicit On 
'/////////////////////////
'/// Form1.vb
'/////////////////////////
Public Class Form1
    Inherits System.Windows.Forms.Form

    ' Windows フォーム デザイナで生成されたコード

    Private mParentClass As Class1
    Friend Sub New(ByRef ParentClass As Class1)
        Me.New()
        Me.mParentClass = ParentClass
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Me.mParentClass.ShowForm2()
        Me.Close()
    End Sub

    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        Me.mParentClass.SetForm1Nothing()
    End Sub

End Class

'/////////////////////////
Option Explicit On 
'/////////////////////////
'/// Form2.vb
'/////////////////////////
Public Class Form2
    Inherits System.Windows.Forms.Form

    ' Windows フォーム デザイナで生成されたコード

    Private mParentClass As Class1
    Friend Sub New(ByRef ParentClass As Class1)
        Me.New()
        Me.mParentClass = ParentClass
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Me.mParentClass.ShowForm1()
        Me.Close()
    End Sub

    Private Sub Form2_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        Me.mParentClass.SetForm2Nothing()
    End Sub

End Class


ひじり  2004-09-30 21:56:28  No: 116593

πさんに一言申し上げたいのですが、
ここ数日のπさんの質問を見ている限り、
クラス、モジュールの違い等の基本知識がかなり欠如しているように
見受けられます。

また、回答をして下さった方のソースを
その都度きちんと理解されていますでしょうか?

基本知識は必要になったときに必要になったところだけ
勉強すればいいものではありません。
一度それなりの本などを購入されてはいかがでしょうか。
先の質問で回答者から出た『@IT』などのサイトでも
基本から勉強することが出来ます。

まずは必須知識を身につけてから質問したほうがよろしいかと思います。
また、HNをころころ変えられてますが(種類は少ないですが)
これは自分の発言に責任を持っていないとみなされてしまいますので、
止めた方がよろしいのではないでしょうか。

初心者であることは恥ずべきことではありませんが、
質問の回数の多さとその内容から、自助努力を怠っているように
見受けられましたので、失礼ながら発言させていただきました。

スレ汚し申し訳ありません。


π  2004-09-30 23:29:16  No: 116594

ひじりさんへ
不快な想いを与えてしまったならすみませんでした。ご指摘ありがとうございます。
ひじりさんがおっしゃられるように、.NETを触ったこともなかった初心者な私にプログラムの必須知識が欠けているのは自負しております。しかし最低限の必須知識は身につけて質問したつもりでした。ただ、自分のやろうとしている処理がモジュールを使うものであったり、クラスを使うものであったりと、その時は本当にわからなかったんですModuleを使うとき、Classを使うとき、System.IO名前空間を使うとき、、始めは何をやっているのか全くわからなかったのですが、今では皆様のお力添えを頂き、少しずつではありますが、分かるようになってきたんです。

クラスってなに?モジュールってなに?始めは右も左も分かりませんでした。ただ前に進んでることだけは分かっていました。ご回答して下さった方々のコードを頂き、ただ単に貼り付けて、思ったようなプログラムができた!そんな次元で満足しているわけでは決してありません!

ご回答して下さった方のソースを基に、クラスとはこういう使い方をするのか!モジュールで宣言すれば他のFORMからも見えるんだな!Newすることで新しくオブジェクトをつくってるんだな!ん?実体化されてないって?あぁなるほど、Newで宣言してないじゃん!・・・・というように今までやってきました。その中でだんだんと自分で解決できるようになってきたんです。もちろん、どんな処理をしているかわからないときは「@IT」などのサイトも参考にさせて頂いています。

初心者なのに生意気だと思われるかもしれませんが、「習うより慣れろ」というスタンスで今までやってきました。人それぞれ考え方は違いますが、私はこれからも「習うより慣れろ」のスタンスでやっていくつもりです。そして質問の回数が多いというのは、自分の努力を怠っているということなのでしょうか。慣れるのは勝手だが質問するなと言われているようでちょっと悲しいです。上の方にも書きましたが、本当に0からのスタートでいろいろな疑問や問題点に当たるのは当たり前だと思います・・。その都度自分でヘルプをみたりサイトを参考したりして解決に努めますが、それでもうまくいかないときにここの掲示板を利用させて頂いていました。過去ログもいろいろなキーワードですべて検索しています。
このスレでも指摘されましたが過去ログを「別フォーム」で検索しても.NETのものでなかったり、ただForm1.hide()としているものであったりと自分のやりたいことと、過去ログが違ったので質問させてもらったんです・・。他のスレでもMACアドレスの取得について過去ログを!とありますけど、System.Management名前空間がどうしても出てこなかったので質問させてもらったんです。私が質問前に書いておくべきでした。すみません。

HNの件は、πとπ+をころころ変えているとのご指摘ですが、発言に責任を持っていないと感じられたようで、申し訳ありませんでした。

最後に、長文となりましたことをお詫び申し上げます。ひじりさんのおかげでもっともっとやる気がでました!!感謝しています!!しかし、このスタンスは貫くつもりです。その時はどうぞよろしくお願いします!!


π  2004-09-30 23:38:34  No: 116595

特攻隊長まるるうさんへ
ソース掲載ありがとうございます!
スタートアップをサブメインにすることで、勝手に実体化させなくて済むんですね!

考え方としては、サブメインからクラスにアクセスして、実体化させることで、Closeできるようにするということでいいのでしょうか。

自分としてもいろいろ試したのですが、クラスにアクセスして実体化させたものについてはCloseできました。しかしスタートアップにForm1や2をもってくると、クラスからShowしていないのでCloseすることができなかたんです。もちろんMe.Close()でできるのですがそうするとすべて消えてしまうという問題にあたるんです。

まるるうさんのコードを貼り付けてみたのですが、クラス内のMeが使えなかったんです><;自分でもいろいろ調べてみてはいますがちょっと苦戦しています。またFriend Sub というのも初めて見たので、その使い方がわかりました!もっとしらべてみますね><!!本当に感謝しています!

なぜできないか原因を追求してみますっ!!!


ひじり  2004-09-30 23:59:10  No: 116596

πさんへ

こちらこそ失礼な発言申し訳ありませんでした。
「習うより慣れろ」というスタンスは私も嫌いではありません。
どちらかというと、私も自分であれこれやってみて覚えていくタイプですから。

私もVB6時代よりここのサイトを利用させて頂いているのですが、
以前とある方から
・質問と質問の間隔が短すぎる
・自分である程度調べてきたという感じが質問から見受けられない
・回答に対するレス(再質問)が早すぎる
  (とある助言を受けて、「調べましたがわかりませんでした」と
    4時間ほど調べた後にレスをしたところ、言われました。)
との叱責を受けたことがあります。

これ以来、
・質問は1日1つまで
・前の質問が片付いていないうちから次の質問をしない
・質問と質問の間は1日以上空ける
・どうやって調べたか、どこまで分かっているのかをきちんと書く
を心がけるようにしています。

早くいろいろ覚えたいその気持ちはとても大切ですが、
掲示板を利用するということは、そこで回答してくださっている人が
自分の時間を貴方の為に割いているということを絶対に忘れないで下さい。

プログラミングは楽しいものです。
いつまでもその気持ちを忘れずに、いつか貴方が助言できる側に
立てるようになることを期待します。
頑張って下さい。


特攻隊長まるるう  2004-10-01 00:33:02  No: 116597

>考え方としては、サブメインからクラスにアクセスして、実体化させることで、Closeできるようにするということでいいのでしょうか。
>まるるうさんのコードを貼り付けてみたのですが、クラス内のMeが使えなかったんです
>なぜできないか原因を追求してみますっ!!!
ボクは何か答えなきゃいけないの?それとも自分で調べるの?
自分で調べるなら結果が出てからレスして欲しい…。

例えば素人レベルの人が自分の素人さ加減に気付いて初心者
レベルの基礎知識を身に付けるために勉強しようと思ったら、
やっぱり次のレス付けるまでの勉強期間として半年くらいは
必要なわけです。
交流掲示板とは違いますので、すぐにレス付ける必要は無いと
思います(違う考えを持ってる人もいるでしょうが)。『しばらく
自分で調べてみます』とかいうレスを付けても構いません。
意見を述べる時は長くなる事もあるでしょう(ボクもたまにします)。

ただ、質問してる時は、なるべく要点を漏らさず簡潔に
何を聞きたいのかハッキリ書いて下さい。

とりあえず
>まるるうさんのコードを貼り付けてみたのですが、クラス内のMeが使えなかったんです
自分の貼り付けたコードが動かないとか言われてるのが心外なので(笑)

[Me(オンラインヘルプ)]より抜粋
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vblr7/html/vakeyMe.asp
>キーワード Me は、次の構文で使用します。
>Class ステートメント

『クラス内のMeが使えなかった』という意味が分かりません。
エラーが出てて、それについて質問してるなら、エラーメッセージは
必ず書いて下さい。どういう操作をしてそうなったか?こちらで
何か調べられる情報を伝える努力をして下さい。

言っておきますがこちらの環境では動作確認取れてますからね?
環境に依存する場合もあるので『動作保証はしません』とか
書くこともありますが、全く動かないままでソース公開する事は
まず、ありませんから、ボクの場合。


π  2004-10-01 10:02:21  No: 116598

こんばんはです><誤解を招いたみたいで、本当に申し訳ありませんでした。
私の環境は.NET2003なんですが、

Friend Sub New(ByRef ParentClass As Class1)
        Me.New()
        Me.mParentClass = ParentClass
End Sub
とするとNew()のところにアンダーラインが入ってしまって引数にParentClassを指定してくださいとメッセージがでてしまうんです・・。

一日いろいろ試していたのですがHide()で対処することにしました><;
どうもありがとうございました><!!


特攻隊長まるるう  2004-10-01 21:44:40  No: 116599

…ああ、本来の『Windows フォーム デザイナで生成されたコード』
を消しちゃったんですね。…しかしそれだと Button1.Click とかも
エラーになるはずですが…。なんか、こう…また基本が分かってない
とか言われちゃうかも?ですねぇ。何が問題ってたくさん説明しなきゃ
いけない事が(ボクにとってw)問題です。しかし途中で止められると
…質問者はそれで満足なんでしょうが、今後、過去ログ検索で利用する
人が困るんですよ。質問の上級者(プログラミング上級者ではない)は、
自分の質問や回答が、後から技術情報を検索したい人に理解しやすい
形になるよう努力します。

多分、分からない言葉がたくさん出てくるでしょうが、基本的な(
ヘルプに載ってる)レベルの事ですので色々勉強して下さい。解説は
中級者が常識として理解できてるレベルに省略させてもらいます。
書籍[VB.NET入門]とかに書いてあるレベルなので、ボクの中では
[VB.NET]プログラマ初心者レベルの話ですが…。…本心は『入門』
できてないんだから初心者にもなってないでしょ?とか思ってます。
そんな質問はするべきでないと思ってます。入門本1冊読むか
セミナー受ければ分かる事を、回答者から時間を奪って説明させてる
わけだから『冗談じゃない』と思ってます。これ書くのに1時間
…時給1,000円くらいの損害を与えられてます…お昼ご飯食べれません
でした。でも管理人さんに削除依頼を出すほどではないと思ってますw。
…でも怒ります。
そのくらいはいいでしょ?労力使ってるんだから。公開した
コードの内容はちょっと高めで、π さんの質問のレベルは
ちょっと低めです。怒られる事は覚悟の上で質問して下さい。
怒られるのが嫌なら入門レベルの実力をどっかでつけてきて下さい。
ここで回答者を使って実力アップする気なら、怒られても文句
言わないで努力して下さい。(←π さんは多少引っ掛かりつつも
できてると思います。これを読んだ他の質問者向けです)
怒るくらいなら回答するな?…解決率が低くなっちゃうじゃ
ナイデスカw…『回答するな!』ってゆーならそれ以前に
『質問するな!』と言いたい…言いたいが…初心者掲示板と
いう事でそこまでは言わない…よう努力します...(  _)_ぱたり

公開したコードの
>    Friend Sub New(ByRef ParentClass As Class1)
は[Windows フォーム デザイナ]によって自動的にコーディング
される
    Public Sub New()
のオーバーロード(引数が違うだけで同じ名称の関数)です。

まず、[ソリューション]に新規フォームを追加し、[Windows 
フォーム デザイナ]の画面(デザイン画面)で追加した新規
フォームにボタンを1個貼り付けて下さい。
追加した新規フォームのコードを表示すると半透明で四角で
囲まれた[ Windows フォーム デザイナで生成されたコード ]
というのが見えると思います。クリックして展開して下さい。
>#Region " Windows フォーム デザイナで生成されたコード "
>       〜いろんなコード〜
>#End Region
になったと思いますが、最初の方に
    Public Sub New()
があると思います。親クラス(公開したコードの Class1)とかで
>    Dim Form1_form As New Form1
>                         ↓同じ意味
>    Dim Form1_form As Form1
>    Form1_form = New Form1
とやった時に呼び出される New はこれの事です。
>#Region " Windows フォーム デザイナで生成されたコード "
>       〜いろんなコード〜
>#End Region
の[〜いろんなコード〜]にざっと目を通して見て下さい。フォームの
プロパティやボタンのプロパティ、コントロールの追加などの
重要なコードが書かれていますね?。
>    ' メモ : 以下のプロシージャは、Windows フォーム デザイナで必要です。
>    'Windows フォーム デザイナを使って変更してください。  
>    ' コード エディタを使って変更しないでください。
という記述もあります。『これは意味が分からない人は触るな!』と
いう意味で『ここを変更するとデザイナが見れなくなったり、フォームが
New 出来なくなったりします。』という意味です。変更しないで下さい。
エラーが出ていると言われた
>        Me.New()
は本来の New を呼び出して、フォームを実体化するのに必要な本来の
処理をやってもらってるわけです。ところが削除されてしまった為に
他に New という関数が無いか探します。
>    Friend Sub New(ByRef ParentClass As Class1)
が見つかります。これは引数を必要とします。公開したコードの Class1 で
>            Me.Form1_form = New Form1(Me)
という風に使ってます。この Me は Class1 で使ってるので Class1 の
実体(特定のインスタンス)を指します(参照します)。引数を必要とする
New なので↓のエラーメッセージが出ます。
>New()のところにアンダーラインが入ってしまって引数にParentClassを指定してくださいとメッセージがでてしまうんです・・。
これは
>クラス内のMeが使えなかった
ではありませんでした。違いが理解できたでしょうか?間違った解釈
を説明された場合、当然正しい回答はできません。エラーメッセージは
ほぼ正しい解釈につながるものです。ぶっちゃけコレが回答なんですが…
まぁ、機械の判断することなので直接の原因を指してなかったり、微妙に
間違ってたりします。回答者はまずこの[エラーメッセージの翻訳]を
します。今後、質問時にエラーメッセージが出てる時は必ず書いて下さい。

>ご回答して下さった方々のコードを頂き、ただ単に貼り付けて、思ったような
>プログラムができた!そんな次元で満足しているわけでは決してありません!
ボクが公開したコードも理解して、必要な部分だけコピーして貼り付けて下さい。
>'/////////////////////////
>Option Explicit On 
>'/////////////////////////
>'/// Form1.vb
>'/////////////////////////
の Form1.vb の部分はファイル名です。デフォルトで作成した時の
ファイル名にしてありますのでファイルをデフォルト設定で作成し、
自動で作成されたコードと見比べ、足りない部分だけ追加して下さい。
コードを削除したり、上書きしたりしないよう気をつけて貼り付けて
下さい。デフォルトでこのファイル名にならない場合は、何か間違って
設定してないかチェックです。

あ、余談ですが、このサンプルコードで本来の New を使って
フォームを実体化すると親クラスの参照が Nothing でエラーに
なるので本来の New を
    Public Sub New()
                   ↓
    Private Sub New()
に変える…もしくは親クラスの参照でエラー処理を入れるよう改良
するのが中級者レベル…。
>またFriend Sub というのも初めて見たので、その使い方がわかりました!
そこのオマケ要素に気付いて調べているのは大変いい事だと思います。
意味が正しく調べられたのなら『スコープを意識しての事ですよね?』
とかレスを付けると回答者の機嫌が良くなりますw。『Protected でも
良いのかと思い調べましたがここでは使えない事が分かりました』…とかね。
『トグルって国語辞典に載ってました』…とか?
『調べました』なんてのは調べてなくても言えます。調べてても調べ方が
悪かったら意味無いんです。評価をしない事もないですが、低いです。
逆に回答者が『頑張って調べましたが丸っきり理解できてないです』と
いった回答を付けたら評価してくれます?しないでしょ?(^^;)

調べたなら『理解度』がこちらに伝わるレスを付けて下さい。


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

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






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