- PR -

子画面の終了方法

投稿者投稿内容
さち
会議室デビュー日: 2003/12/22
投稿数: 5
投稿日時: 2003-12-22 16:54
こんにちわ。VB.NET初心者です。
どなたか分かる方教えてください。

下記のような処理を行いたいのです。
・親画面の子画面ボタンを押したら、子画面を親画面の上に表示する。
・親画面の終了ボタンが押されたら、子画面も同時に終了させる。

現在のコーディング方法:
@親画面DLLから子画面DLL.Main関数をよぶ。

Private Sub cmdCmd1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles cmdCmd1.Click

Dim clsAAA As New AAA.frmAAA()

'子画面呼び出し
clsAAA.AAA_Main()

End Sub

A子画面DLL.Mainから、Me.Showする。

Public Sub AAA_Main()

'子画面の表示
Me.Show()

End Sub

この処理に、親の終了ボタンが押されたら、子画面を終了する。
という処理を追加したいのですが、どうもうまく行きません。
親のほうでclsAAAをモジュール変数にして、終了ボタン押下時に
Closeをかけると、閉じる事は出来るのですが、2回目以降に
子画面呼び出しの部分で落ちてしまいます。

どなたか分かりましたら教えてください。
お願いします。
ぢゃん♪
大ベテラン
会議室デビュー日: 2003/06/12
投稿数: 208
お住まい・勤務地: 都内
投稿日時: 2003-12-22 17:14
引用:

さちさんの書き込み (2003-12-22 16:54) より:
(1)親画面DLLから子画面DLL.Main関数をよぶ。
(2)子画面DLL.Mainから、Me.Showする。

親画面から子画面.Showはできませんか?
引用:

親のほうでclsAAAをモジュール変数にして、終了ボタン押下時に
Closeをかけると、閉じる事は出来るのですが、2回目以降に


なぜ「モジュール変数」にしていますか?
親画面のインスタンス変数にしてしまえばいいはずです。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-12-22 17:14
 引用されているのが全文ではないですよね・・・

 質問します。
1.この通りのコードとして、「子画面」ボタンを2回クリックしたら、どうなりますか?
↑仕様と実装が一致していますか、という意味です。

2.「親の終了ボタン」というのは、「親が終了するとき」と考えてよろしいですか?その前提で、「終了」には開発者が付けた「終了」ボタン以外に、「右上の×」、「左上アイコンからの終了」、「[ALT]+[F4]」がありますが、これらの時はどうしましょう?
↑「終了」をキャンセルできる(できるとして)のが、「終了」ボタンの時だけではないですか、という意味です。

3.『2回目以降に子画面呼び出しの部分で落ち』るとき、どの部分で、どのようなエラーメッセージがでますか?
↑2回目?子画面だけを消すのは、どうやってます?
さち
会議室デビュー日: 2003/12/22
投稿数: 5
投稿日時: 2003-12-22 17:45
[/quote]
なぜ「モジュール変数」にしていますか?
親画面のインスタンス変数にしてしまえばいいはずです。
[/quote]

Closingイベントの中でclsAAA.Closeとやりたかったので
モジュール変数としました。

Shared clsAAA As New AAA.frmAAA()でもやってみたのですが同じ結果でした。
次の処理をした際におちます。
@親画面の子画面ボタンにて子画面を表示する。
A子画面の終了又は「×」ボタンで子画面を終了する。
B親画面の子画面ボタンをもう一度おす。

Bの時に、clsAAA.Main を呼び出す部分でおちています。
エラーメッセージは
「インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。」です。
さち
会議室デビュー日: 2003/12/22
投稿数: 5
投稿日時: 2003-12-22 18:01
1.この通りのコードとして、「子画面」ボタンを2回クリックしたら、どうなりますか?
↑仕様と実装が一致していますか、という意味です。

 このコードでは、2回クリックした際にも正しく子画面を呼ぶ事が出来ています。
 ただ子画面を終了させるコードを入れてない状態です。
 子画面を終了させるコードを入れる際に、クラス変数をモジュールでとる必要があると
 考えたので「Dim clsAAA As New AAA.frmAAA()」をモジュールの先頭に持っていきました。それで、親画面の終了ボタン押下時に子画面も終了させるという処理はできたのですが、
 子画面を2回連続で呼ぶ時に落ちてしまいました。

2.「親の終了ボタン」というのは、「親が終了するとき」と考えてよろしいですか?その前提で、「終了」には開発者が付けた「終了」ボタン以外に、「右上の×」、「左上アイコンからの終了」、「[ALT]+[F4]」がありますが、これらの時はどうしましょう?
↑「終了」をキャンセルできる(できるとして)のが、「終了」ボタンの時だけではないですか、という意味です。

 「右上の×」等のときも「終了」ボタン押下時と同様の処理にしたいです。
 フォームのClosingイベントにて、子画面を終了させる処理を入れれば、問題ないと考えているのですが。。。


3.『2回目以降に子画面呼び出しの部分で落ち』るとき、どの部分で、どのようなエラーメッセージがでますか?
↑2回目?子画面だけを消すのは、どうやってます?

Private Sub cmdCmd1_Click(...) Handles cmdCmd1.Click

'子画面呼び出し
clsAAA.AAA_Main() ←ココでおちます。

End Sub
子画面だけを消す時は、子画面の処理にて、
「Me.DialogResult = DialogResult.OK」を行っています。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-12-23 00:31
 まず、コードの意味を考えましょう。

Public Class AAA
 Dim Valiable As New SomeClass
End Class

さて、このValiableに対して、「New」されるのはいつでしょう?MSDNによると、『オブジェクトを即時に作成できるキーワードです。オブジェクト変数を宣言するときに New キーワードを指定すると、Dim ステートメントの実行時にオブジェクトのインスタンスが新規作成されます。』となっています。では、「Dimステートメントが実行されるとき」というのはいつでしょう?
これについては私は詳しくないのですが、おそらくそのクラスのインスタンスが作られるとき、ではないでしょうか。そうであるなら、Valiableのインスタンスは1つしかないことになります。
#メソッド内で行えば、そのメソッドで「実行されるとき」は明白ですけどね



 つまり、Moduleブロックに書いたときは「アプリケーションが実行されるとき」、Classのインスタンス変数にしたときには「クラスがインスタンス化されるとき」の、どちらにしても1回だけしか生成されない、ということです。
 1回しか生成されていないので、それをCloseすると、当然次は開くことができません。



 仕様では「複数開くことができる」ようなので、インスタンスを複数用意する必要があります。
 親は、生成したすべての子インスタンスを覚えておく必要があります。
 子は、自分が終了することを親に伝え、親が覚えているインスタンスを削除してもらいます。
 親が終了するときには、残っている子すべてを強制的に終了させます。



 家なので環境がありません。直打ちなので適切に修正してください。

Public Class 親フォーム
' 子フォームのインスタンスをしまう場所を用意する
Protected ChildrenForm As New ArrayList

Protected Sub クリックイベント
 Dim cForm As New 子フォーム ' 新しいフォームインスタンスを作り
 cform.ParentForm = Me ' 親参照をセットし
 cForm.Show() ' 表示して
 ChildrenForm.Add(cForm) ' 格納する
End Sub

Public Sub DeleteChildForm(Child As 子フォーム)
 ' インスタンス参照を削除する
 ChildrenForm.Remove(Child)
End Sub

Public Sub Closing(引数) Handles 親フォーム.Closing
 ' 現在残っている子フォームをすべて閉じる
 dim cnt As Integer
 For cnt = 0 to ChildrenForm.Count - 1
  ChildrenForm.Item(cnt).Close()
 Next
 ChildrenForm.Clear()
End Sub
End Class

Public Class 子フォーム
 Public ParentForm as 親フォーム
 Protected Sub Closing(引数) Handles 子フォーム.Closing
  ParentForm.DeleteChildForm(Me) ' 親の登録を削除
  ParentForms = Nothing ' いるかなぁ?
 End Sub
End Class

こんな感じ?



 こんなことしなくても、作りっぱなしでもいいように思います。アプリケーションが終了するときには、すべてのオブジェクトが破棄されますから(しかし、OSにそれを実行してもらうのは行儀が悪い、けど)。
さち
会議室デビュー日: 2003/12/22
投稿数: 5
投稿日時: 2003-12-23 14:25
引用:

Jittaさんの書き込み (2003-12-23 00:31) より:
Public Sub Closing(引数) Handles 親フォーム.Closing
 ' 現在残っている子フォームをすべて閉じる
 dim cnt As Integer
 For cnt = 0 to ChildrenForm.Count - 1
  ChildrenForm.Item(cnt).Close()
 Next
 ChildrenForm.Clear()
End Sub



Jittaさんありがとうございます。
教えていただいた方法でやっているのですが、
「ChildrenForm.Item(cnt).Close()」のところで
Closeというメンバは無いようです。。。

別のメンバを使う必要があるのでしょうか?
分かりましたら教えてください。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-12-23 21:21
引用:

さちさんの書き込み (2003-12-23 14:25) より:

Jittaさんありがとうございます。
教えていただいた方法でやっているのですが、
「ChildrenForm.Item(cnt).Close()」のところで
Closeというメンバは無いようです。。。


 キャストしてください。
CType(ChildrenForm.Item(cnt), Form).Close()

 ArrayList.ItemはObjectクラスなので、何でも入ります。入るときはいいのですが、出すときは「どんなクラス」か指定してやる必要があります。

スキルアップ/キャリアアップ(JOB@IT)