サブフォームからメインフォームを操作し、サブフォームの前に表示させる への返答
投稿で使用できる特殊コードの説明。(別タブで開きます。)
以下の返答は逆順(新しい順)に並んでいます。
投稿者 こじろー  (社会人)
投稿日時
2022/2/22 19:33:20
るきおさん。魔界さん。どうもありがとうございました。
投稿者 こじろー  (社会人)
投稿日時
2022/2/22 19:31:38
>Form1 の中でも New は使わずに、「Form2.Show(Me)」 で表示させるようにして、統一性を図りましょう
で
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form2.show(Me)
Form3.show(Me)
End Sub
End Class
で、Form2,3のボタンは正常に動きました。
で
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form2.show(Me)
Form3.show(Me)
End Sub
End Class
で、Form2,3のボタンは正常に動きました。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2022/2/22 12:35:23
BringToFront や SendToBack は、Owner での親子関係や TopMost の最前面表示を
超えて切り替える事はできません。あくまでも、マウス操作で切り替えられる範囲の切り替えだけです。
> で、だめでした。無理なようです。
提示されたコードを見る限り、幾つか不自然な個所があります。
f (Form2) の Owner は Me (Form1)
f2 (Form3) の Owner も Me (Form1) になっているため、
この場合の親子関係はこのようになります。
Form1 は親なので、子である Form2 や Form3 よりも手前に来ることはできません。
Owner を一切指定しないのであれば、Form1 が手前に来ることもできます。
Form2 と Form3 は兄弟なので、本来であればどちらを手前にすることもできるのですが、
今回は Form2 が TopMost ですが、Form3 はそうではないため、
Form2 が常時手前にくることになります。
もしも TopMost を設定したウィンドウが複数あった場合には、
TopMost 同士の中でのみ、前面/背面の切り替えが可能です。
上記の仕様について、認識されていますか?
結果として、Form2 が最前面表示、Form1 が最背面で、その間に Form3 がくる形となります。
もしもそれでは都合が悪いというのであれば、TopMost や Owner の指定を
見直してみてください。BringToFront を用いるのは、その後の話です。
> Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
> Form3.BringToFront()
> End Sub
Form2/Form3 が表示されている最中に、Form1 の Button1 をもう一度押しててみてください。
押した数だけ、Form2 や Form3 が生成・表示されますよね?
これは、Form1 の Button1 内で
「Dim f As New Form2」
「Dim f2 As New Form3」
として、Form3 を毎回 【New】で生成し、それを【Show】しているためです。
たとえば Form3 を生成した後で、
Dim f2 As New Form3
f2.Text = Now.ToString("HH:mm:ss.fff")
のように、いつ生成したのかをタイトルに記録しておくと、
複数起動したときに、どちらが先に生成したものかを確認出来るでしょう。
一方、Form2 で操作しているのは、それらとは無関係の
Form3.BringToFront()
です。
f2 な Form3 インスタンスは Show していましたが、
Form3 な Form3 インスタンスはまだ Show したことが無いので、
これは「まだ表示されていないフォームを手前に表示しようとしている」ことになります。
Form1 で「New」したフォームを操作したいのであれば、複数起動される可能性あるフォームのうち、
どのフォームを手前に表示したいのか、そのインスタンスを明示して BringToFront する必要があります。
たとえば下記のようにすれば、現在開かれている Form3 フォームを、
順次手前に持ってくることになります。(Owner や TopMost の壁は越えられませんが)
一方、そういった明示的なインスタンス管理を行わず、暗黙のフォーム変数で操作したいのなら
Form1 の中でも New は使わずに、「Form2.Show(Me)」 で表示させるようにして、統一性を図りましょう。
超えて切り替える事はできません。あくまでも、マウス操作で切り替えられる範囲の切り替えだけです。
> で、だめでした。無理なようです。
提示されたコードを見る限り、幾つか不自然な個所があります。
f (Form2) の Owner は Me (Form1)
f2 (Form3) の Owner も Me (Form1) になっているため、
この場合の親子関係はこのようになります。
Form1
┣Form2
┗Form3
Form1 は親なので、子である Form2 や Form3 よりも手前に来ることはできません。
Owner を一切指定しないのであれば、Form1 が手前に来ることもできます。
Form2 と Form3 は兄弟なので、本来であればどちらを手前にすることもできるのですが、
今回は Form2 が TopMost ですが、Form3 はそうではないため、
Form2 が常時手前にくることになります。
もしも TopMost を設定したウィンドウが複数あった場合には、
TopMost 同士の中でのみ、前面/背面の切り替えが可能です。
上記の仕様について、認識されていますか?
結果として、Form2 が最前面表示、Form1 が最背面で、その間に Form3 がくる形となります。
もしもそれでは都合が悪いというのであれば、TopMost や Owner の指定を
見直してみてください。BringToFront を用いるのは、その後の話です。
> Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
> Form3.BringToFront()
> End Sub
Form2/Form3 が表示されている最中に、Form1 の Button1 をもう一度押しててみてください。
押した数だけ、Form2 や Form3 が生成・表示されますよね?
これは、Form1 の Button1 内で
「Dim f As New Form2」
「Dim f2 As New Form3」
として、Form3 を毎回 【New】で生成し、それを【Show】しているためです。
たとえば Form3 を生成した後で、
Dim f2 As New Form3
f2.Text = Now.ToString("HH:mm:ss.fff")
のように、いつ生成したのかをタイトルに記録しておくと、
複数起動したときに、どちらが先に生成したものかを確認出来るでしょう。
一方、Form2 で操作しているのは、それらとは無関係の
Form3.BringToFront()
です。
f2 な Form3 インスタンスは Show していましたが、
Form3 な Form3 インスタンスはまだ Show したことが無いので、
これは「まだ表示されていないフォームを手前に表示しようとしている」ことになります。
MsgBox( Form3.Visible ) 'まだ表示されていないので False が表示される
MsgBox( Form3.Text ) ' Form1 で「生成時刻」をセットしたのとは別インスタンスなので、既定値のまま
Form3.BringToFront() 'まだ表示されていないフォームなので、手前に表示しようがない
Form1 で「New」したフォームを操作したいのであれば、複数起動される可能性あるフォームのうち、
どのフォームを手前に表示したいのか、そのインスタンスを明示して BringToFront する必要があります。
たとえば下記のようにすれば、現在開かれている Form3 フォームを、
順次手前に持ってくることになります。(Owner や TopMost の壁は越えられませんが)
For Each f As Form3 In Application.OpenForms.OfType(Of Form3)()
f.BringToFront()
Next
一方、そういった明示的なインスタンス管理を行わず、暗黙のフォーム変数で操作したいのなら
Form1 の中でも New は使わずに、「Form2.Show(Me)」 で表示させるようにして、統一性を図りましょう。
投稿者 こじろー  (社会人)
投稿日時
2022/2/22 09:10:02
Imports System.Windows.Forms
Imports Microsoft.Win32
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim f As New Form2
f.Owner = Me
f.TopMost = True
f.Show()
Dim f2 As New Form3
f2.Owner = Me
'f.TopMost = True
f2.Show()
End Sub
End Class
Imports System.Windows.Forms
Imports Microsoft.Win32
Public Class Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form3.BringToFront()
End Sub
End Class
Imports System.Windows.Forms
Imports Microsoft.Win32
Public Class Form3
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form2.BringToFront()
End Sub
End Class
で、だめでした。無理なようです。
Imports Microsoft.Win32
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim f As New Form2
f.Owner = Me
f.TopMost = True
f.Show()
Dim f2 As New Form3
f2.Owner = Me
'f.TopMost = True
f2.Show()
End Sub
End Class
Imports System.Windows.Forms
Imports Microsoft.Win32
Public Class Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form3.BringToFront()
End Sub
End Class
Imports System.Windows.Forms
Imports Microsoft.Win32
Public Class Form3
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form2.BringToFront()
End Sub
End Class
で、だめでした。無理なようです。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2022/2/21 21:18:45
> 簡単な例を、改めて作ってみました。
その例の場合、Form2 の Owner が Form1 になっていますよね。
そのため、Form2 が Form1 よりも手前に来ることはありません。
Owner を指定していなければ、BringToFront で手前に来ます。
たとえば
Form2 の Owner が Form1 で
Form3 の Owner が Form1 の場合、
Form2 を Form3 より手前にしたり、Form3 を Form2 より手前にすることはできます。
しかし Form1 が Form2 や Form3 よりも手前に来ることはできません。
Form1 がそれらのオーナーだからです。
その例の場合、Form2 の Owner が Form1 になっていますよね。
そのため、Form2 が Form1 よりも手前に来ることはありません。
Owner を指定していなければ、BringToFront で手前に来ます。
たとえば
Form2 の Owner が Form1 で
Form3 の Owner が Form1 の場合、
Form2 を Form3 より手前にしたり、Form3 を Form2 より手前にすることはできます。
しかし Form1 が Form2 や Form3 よりも手前に来ることはできません。
Form1 がそれらのオーナーだからです。
投稿者 こじろー  (社会人)
投稿日時
2022/2/21 20:29:56
簡単な例を、改めて作ってみました。
Imports System.Windows.Forms
Imports Microsoft.Win32
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim f As New Form2
f.Owner = Me
'f.TopMost = True
f.Show()
End Sub
End Class
mports System.Windows.Forms
Imports Microsoft.Win32
Public Class Form2
'Public Property MainForm As Form1 <-使いません。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form1.BringToFront()
'MainForm.BringToFront()
End Sub
End Class
で、やってみましたが、だめでした。VS2013です。
Imports System.Windows.Forms
Imports Microsoft.Win32
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim f As New Form2
f.Owner = Me
'f.TopMost = True
f.Show()
End Sub
End Class
mports System.Windows.Forms
Imports Microsoft.Win32
Public Class Form2
'Public Property MainForm As Form1 <-使いません。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form1.BringToFront()
'MainForm.BringToFront()
End Sub
End Class
で、やってみましたが、だめでした。VS2013です。
投稿者 るきお  (社会人)
投稿日時
2022/2/21 19:05:32
単純にFormの前後関係を変える用途ではOwnerやTopMostは目的も違いますし使いにくいです。
BringToFrontメソッドはフォームを前に表示する機能なのでこれを利用するとよいと思います。
私ならこう書きます。
Form1
Message_Form
ちなみにMessage_Form側と SendToBack する方法もありますが、これだと一番後ろに回されます。
BringToFrontメソッドはフォームを前に表示する機能なのでこれを利用するとよいと思います。
私ならこう書きます。
Form1
Public Class Form1
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim f As New Message_Form
f.MainForm = Me
f.Show()
End Sub
End Class
Message_Form
Public Class Message_Form
Public Property MainForm As Form1
Private Sub OK_Button_Click(sender As Object, e As EventArgs) Handles OK_Button.Click
MainForm.BringToFront()
End Sub
End Class
ちなみにMessage_Form側と SendToBack する方法もありますが、これだと一番後ろに回されます。
投稿者 こじろー  (社会人)
投稿日時
2022/2/21 17:17:31
以下、簡単な例です。
メインフォーム(Form1)と、2つ目のフォーム(Message_Form)は、メインフォームが大きく、二つ目のフォームと重なります。
メインフォームのButton3に
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim f As New Message_Form
f.Owner = Me
f.TopMost = True
f.Show()
End Sub
2つ目のフォームのOKButtonに、以下の記述をして、Form1の前に来た2つ目のフォームのMessage_FormがOKボタンを押すと、Form1がその前に来るようにしたいのです。
Public Class Message_Form
Private Sub OK_Button_Click(sender As Object, e As EventArgs) Handles OK_Button.Click
Me.TopMost = Not Me.TopMost
Owner.TopMost = True
End Sub
End Class
Me.TopMost = Not Me.TopMostはMe.TopMost =Falseでも行いましたが、できません。
無理でしょうか?
メインフォーム(Form1)と、2つ目のフォーム(Message_Form)は、メインフォームが大きく、二つ目のフォームと重なります。
メインフォームのButton3に
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim f As New Message_Form
f.Owner = Me
f.TopMost = True
f.Show()
End Sub
2つ目のフォームのOKButtonに、以下の記述をして、Form1の前に来た2つ目のフォームのMessage_FormがOKボタンを押すと、Form1がその前に来るようにしたいのです。
Public Class Message_Form
Private Sub OK_Button_Click(sender As Object, e As EventArgs) Handles OK_Button.Click
Me.TopMost = Not Me.TopMost
Owner.TopMost = True
End Sub
End Class
Me.TopMost = Not Me.TopMostはMe.TopMost =Falseでも行いましたが、できません。
無理でしょうか?