none
MDIで子フォームが全て閉じたときに親フォーム上のコントロールにフォーカスを移したい RRS feed

  • 質問

  • VB2005 でMDIアプリを作成しています。

    親フォームにTextBox1コントロールがあるとして、

    子フォームが全て閉じた際に、親フォームのTextBox1コントロールにフォーカスを移したいと思い、

     

        Private Sub Form1_MdiChildActivate(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MdiChildActivate
            If Me.ActiveMdiChild Is Nothing Then
                Me.TextBox1.Focus()
            End If
        End Sub

     

    と記載しているのですが、From1.ActiveControl がTextBox1、TextBox1.FocusedプロパティはFalseになります。

     

    Focusも移すにはどのようにしたらよいのでしょうか?

    2008年1月7日 5:07

回答

  • とりあえず、動作したので。

    #あらゆる場面で通用するかは未確認。

     

    親:Form1にTextBox1とButton1

    子:Form2

     

    Public Class Form1

        Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown

            _MDIClient = GetMDIClient()

        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

            Dim f As New Form2
            f.MdiParent = Me
            f.Show()

        End Sub

        Private WithEvents _MDIClient As MdiClient

        Private Function GetMDIClient() As MdiClient

            For Each ctl As Control In Me.Controls
                If TypeOf ctl Is MdiClient Then
                    Return DirectCast(ctl, MdiClient)
                End If
            Next
            Return Nothing

        End Function

        Private Sub _MDIClient_ControlRemoved(ByVal sender As Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles _MDIClient.ControlRemoved

            If Me.ActiveMdiChild Is Nothing Then
                TextBox1.Focus()
            End If

        End Sub

    End Class

    2008年1月8日 1:13

すべての返信

  • nasv さん、こんにちは。

     

    まず、MdiChildActivate イベントが自分の思ったタイミングで実行されていますでしょうか?
    イベント名からすると、

     

     nasv さんからの引用

    子フォームが全て閉じた際に、親フォームのTextBox1コントロールにフォーカスを移したいと思い、

     

    そういったタイミングではないと思われます。
    Focus メソッドは実行されていないのでしょう。

    TextBox1 が ActiveControl に設定されるのは MdiChildForm が消えるからだと思われます。
    この場合、ActiveControl = A として A.Focused が False というのがありえます。

    素直に親 Form で MdiChildForm の Closed イベントなどを拾っていた方が良いのではないでしょうか。

    2008年1月7日 5:47
  •  じゃんぬねっと さんからの引用

    素直に親 Form で MdiChildForm の Closed イベントなどを拾っていた方が良いのではないでしょうか。

     

    申し訳ありません。

    親 Form でMdiChildForm の Closed イベント を拾うというのは一般的にどのように行うべきなのでしょうか?

    MdiChildForm の Closed イベントで親フォームの Sub を呼ぶような感じでしょうか?

    2008年1月7日 6:20
  •  nasv さんからの引用

    親 Form でMdiChildForm の Closed イベント を拾うというのは一般的にどのように行うべきなのでしょうか?

    MdiChildForm の Closed イベントで親フォームの Sub を呼ぶような感じでしょうか?


    一般的かどうかと尋ねられると閉口しがちな私ですが、

    親 Form で MdiChildForm のインスタンスを生成する時に、イベント プロシージャと紐付けおく方法になると思います。

    VB.NET
    Private Sub Button1_Click(...) Handles Button1.Click

        Dim cChildForm1 As New ChildForm1()

        AddHandler cChildForm.FormClosed, AddressOf ChildForms_FormClosed()

        Me.IsMdiContainer = True


        ' この後に ChildForm を表示する

        cChildForm1.MdiParent = Me

        cChildForm1.Show()

    End Sub

     

    Private Sub ChildForms_FormClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs)

        If (Me.MdiChildren Is Nothing) OrElse (Me.MdiChildren.Length <= 0) Then

            Me.TextBox1.Focus()

        End If

    End Sub


    適当に書きましたが、たぶんこんな感じではないでしょうか。

    2008年1月7日 6:36
  • やってみましたが動きは変わりませんでした。

     

    ちなみに Form.MdiChildActivate  イベントは

    『マルチ ドキュメント インターフェイス (MDI) 子フォームが MDI アプリケーション内でアクティブになった場合、または閉じた場合に発生します。』

    となっており、実際に動かしてみると

    子フォームのClosedイベント⇒ChildForms_FormClosed⇒親フォームのMdiChildActivateイベント

    の順で発生しております。

     

    また子フォームのClosedイベントの際は Me.MdiChildren は Nothing ではないので親Formのコントロールにはうまくフォーカスが当たらないようです。

     

    MdiChildActivateよりも後でなにかイベントを取るしかないようですので、最終的にはTimerとかに頼るしかないのでしょうか?

     

     

    2008年1月7日 7:02
  • とりあえず、動作したので。

    #あらゆる場面で通用するかは未確認。

     

    親:Form1にTextBox1とButton1

    子:Form2

     

    Public Class Form1

        Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown

            _MDIClient = GetMDIClient()

        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

            Dim f As New Form2
            f.MdiParent = Me
            f.Show()

        End Sub

        Private WithEvents _MDIClient As MdiClient

        Private Function GetMDIClient() As MdiClient

            For Each ctl As Control In Me.Controls
                If TypeOf ctl Is MdiClient Then
                    Return DirectCast(ctl, MdiClient)
                End If
            Next
            Return Nothing

        End Function

        Private Sub _MDIClient_ControlRemoved(ByVal sender As Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles _MDIClient.ControlRemoved

            If Me.ActiveMdiChild Is Nothing Then
                TextBox1.Focus()
            End If

        End Sub

    End Class

    2008年1月8日 1:13