- PR -

VB.NETでのフォーム遷移について

投稿者投稿内容
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-03-04 11:53
引用:

よねKENさんの書き込み (2004-03-04 10:03) より:

Closeしてはだめというのはその通りですが、
Disposeを引き合いに出しているのは違うと思います。



Form.Showで呼び出したときのClose → Disposeと同等の処理が行われる
Form.ShowDialogで呼び出したときのClose → 破棄はされないが再利用禁止
アプリケーションルートとなったときのClose → ???

3つの動作があるということになりますか??

引用:
Application.Runより:
メモ このメソッドが返される前に、 Form クラスの Dispose メソッドが呼び出されます。


 メインフォームのCloseメソッドをコールした段階でどのような処理が行われるのかわかりませんが、Disposeはされるようです。←いや、そういう問題じゃないって


引用:
Form.Closeより:
フォームが閉じると、オブジェクト内で作成されたすべてのリソースが閉じ、フォームが破棄されます。


 MSのガイドラインでは、リソースを閉じる操作はDisposeに集約するようになっています。「リソースが閉じ」ということは、Disposeがコールされていると考えても良いと思います。
↑↑↑
「アンマネージ リソースをクリーンアップするための Finalize および Dispose の実装」これはアンマネージリソースのみ?しかし、Win32APIを使用している以上、アンマネージリソースも使っているはず。


*追加

> アプリケーション全体をDisposeすることになります。

これが問題ですね。確かに、これは間違いです。適切な言葉が思い浮かばなかったのです。
「アプリケーションが動作する土台を閉じてしまうので、アプリケーションが終了するのと同等です」??

[ メッセージ編集済み 編集者: Jitta 編集日時 2004-03-04 12:00 ]
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2004-03-04 13:31
#参考になるかどうか判りませんが...。

私の場合、フォーム遷移する/しないに関わらず、「入り口と出口はそれぞれ一つ」を心がけ、常にSub Mainをスタートアップに指定しています。

以下の例では、各フォームをメインとなるクラスのメンバとして、フォームの Load および Closed イベントを捕まえて、カウンタが 0 になったら(開いているフォームが無くなったら)、アプリケーションを終了しています。
こんな感じの作りにすると、各フォーム側ではアプリケーション全体の状態とかをそれほど意識しなくても済むのではないでしょうか。

コード:
' メインクラス
Public Class Class1

    Public Shared WithEvents F1 As Form1
    Public Shared WithEvents F2 As Form2
    Public Shared WithEvents F3 As Form3

    Private Shared Counter As Integer = 0

    Private Sub New()
        F1 = New Form1
        F1.Show()
        Application.Run()
    End Sub

    Public Shared Sub Main()
        Dim C1 As Class1 = New Class1
    End Sub

    Private Shared Sub Form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles F1.Load, F2.Load, F3.Load
        Counter += 1
    End Sub

    Private Shared Sub Form_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles F1.Closed, F2.Closed, F3.Closed
        Counter -= 1

        If Counter.Equals(0) Then
            Application.Exit()
        End If
    End Sub

End Class

' フォーム
Public Class Form1
    Inherits System.Windows.Forms.Form

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Class1.F2 = New Form2
        Class1.F2.Show()
        Me.Close()
    End Sub
End Class


よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2004-03-04 13:58
引用:

Jittaさんの書き込み (2004-03-04 11:53) より:
> アプリケーション全体をDisposeすることになります。

これが問題ですね。確かに、これは間違いです。適切な言葉が思い浮かばなかったのです。
「アプリケーションが動作する土台を閉じてしまうので、アプリケーションが終了するのと同等です」??



メインフォームをCloseするとアプリケーションが終了する理由ですが、
Application.Run メソッド (Form)のヘルプに書いてあります。

>> このメソッドは、 Closed イベントの mainForm パラメータにイベント ハンドラを追加します。
>> イベント ハンドラは、 ExitThread を呼び出して、アプリケーションをクリーンアップします。

メインフォームをCloseするとApplication.ExitThreadが呼ばれるため、
Applicatoin.Run(Form)の実行が終了し、そのままMainメソッドを抜けアプリが終了します。
ゆうじゅん
ぬし
会議室デビュー日: 2004/01/16
投稿数: 347
投稿日時: 2004-03-04 14:06
ApplicationContextを使う手もあるみたいですね

(追加)
コード:

class MyApplicationContext : ApplicationContext
{
private Form1 form1;
private Form2 form2;

private MyApplicationContext()
{
form1 = new Form1();
form1.Closed += new EventHandler(OnFormClosed);
form1.Show();
}

private void OnFormClosed(object sender, EventArgs e)
{
if (sender is Form1)
{
form2 = new Form2();
form2.Closed += new EventHandler(OnFormClosed);
form2.Show();
}
else if (sender is Form2)
{
ExitThread();
}

}

[STAThread]
static void Main()
{
MyApplicationContext context = new MyApplicationContext();
Application.Run(context);
}
}



[ メッセージ編集済み 編集者: ゆうじゅん 編集日時 2004-03-04 14:20 ]
ヤクルト400
会議室デビュー日: 2004/02/16
投稿数: 18
投稿日時: 2004-03-04 20:43
おそくなりました、便乗質問していたヤクルト400です。
ご回答ありがとうございます。

引用:

Form@がスタートアップの画面です。
Form@:FormAをインスタンス化する
Form@:FormAのOwnerにForm@をセットする
Form@:Form@がFormAをShowする
Form@:Form@をHideする
FormA:FormAをCloseする
FormA:Owner(Form@)をShowする


よねKENさん、Jittaさんのご指摘どおり、逆にするとアプリが終了することは
なくなりました。
でもなぜか、FormAで持っているDataGridだけ画面から消えてなくなり、
FormAは閉じてくれません。
デバッグすると、上記の処理は確かに通っているのに、画面がそのまま残っています。
ShowDialogにすると大丈夫なんですけど・・・

もともとSubMainにしようか迷っていたので、今回はきくちゃんさんのSubMainに変更して
対応しようかと考えています。

引用:

hideするならownerに設定する必要はないのでは?←「自分が閉じた後に表示するフォーム」を知らなければいけないのか。


はい、FormAからForm@は直接見えないので、「Form1.Show」という記述ができず、Ownerにセットしています。


ご回答いただいたみなさん、ありがとうございました

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