トップ回答者
MDIで子フォームが全て閉じたときに親フォーム上のコントロールにフォーカスを移したい

質問
-
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も移すにはどのようにしたらよいのでしょうか?
回答
-
とりあえず、動作したので。
#あらゆる場面で通用するかは未確認。
親: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 NothingEnd 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 IfEnd Sub
End Class
すべての返信
-
nasv さん、こんにちは。
まず、MdiChildActivate イベントが自分の思ったタイミングで実行されていますでしょうか?
イベント名からすると、nasv さんからの引用 子フォームが全て閉じた際に、親フォームのTextBox1コントロールにフォーカスを移したいと思い、
そういったタイミングではないと思われます。
Focus メソッドは実行されていないのでしょう。
TextBox1 が ActiveControl に設定されるのは MdiChildForm が消えるからだと思われます。
この場合、ActiveControl = A として A.Focused が False というのがありえます。
素直に親 Form で MdiChildForm の Closed イベントなどを拾っていた方が良いのではないでしょうか。 -
nasv さんからの引用 親 Form でMdiChildForm の Closed イベント を拾うというのは一般的にどのように行うべきなのでしょうか?
MdiChildForm の Closed イベントで親フォームの Sub を呼ぶような感じでしょうか?
一般的かどうかと尋ねられると閉口しがちな私ですが、親 Form で MdiChildForm のインスタンスを生成する時に、イベント プロシージャと紐付けおく方法になると思います。
VB.NETPrivate Sub Button1_Click(...) Handles Button1.ClickDim 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
適当に書きましたが、たぶんこんな感じではないでしょうか。 -
やってみましたが動きは変わりませんでした。
ちなみに Form.MdiChildActivate イベントは
『マルチ ドキュメント インターフェイス (MDI) 子フォームが MDI アプリケーション内でアクティブになった場合、または閉じた場合に発生します。』
となっており、実際に動かしてみると
子フォームのClosedイベント⇒ChildForms_FormClosed⇒親フォームのMdiChildActivateイベント
の順で発生しております。
また子フォームのClosedイベントの際は Me.MdiChildren は Nothing ではないので親Formのコントロールにはうまくフォーカスが当たらないようです。
MdiChildActivateよりも後でなにかイベントを取るしかないようですので、最終的にはTimerとかに頼るしかないのでしょうか?
-
とりあえず、動作したので。
#あらゆる場面で通用するかは未確認。
親: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 NothingEnd 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 IfEnd Sub
End Class