モーダル制御について

タグの編集
投稿者 さしみマン  (社会人) 投稿日時 2021/11/10 16:01:21
モーダル制御の方法について質問させてください。

「form1」「form2」「form3」があるとして、「form1」に「form2」「form3」が開けるボタンを用意します。

----フォーム「form1」のコード----
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Form2.Show()
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Form3.ShowDialog()
    End Sub

このようなコードを書くと当たり前ですが、「form3」を出すと他のフォームは触れなくなります。
ただ、「form3」を出している状態で「form2」だけは触れるようにしたいです。

何か良い方法はございませんでしょうか?

投稿者 魔界の仮面弁士  (社会人) 投稿日時 2021/11/10 16:59:24
複数のフォームを触れるようにしたいのであれば、
そもそもモーダルを選択すべきでは無いと思いますよ。

たとえば Form3 もモードレスに切り替えて、
「Form3 の表示中は Form1 を Enabled = False にしておく」では駄目でしょうか。


> 「form3」を出している状態で「form2」だけは触れるようにしたいです。
どうしても Form3 をモーダルにしておきたいのであれば、
Form3 を表示する前に Form2 を Hide() しておき、
モーダル表示した Form3 の Shown イベントで Form2 を表示しなおすという手があります。
ただしこの方法は、フォーム間の依存関係が複雑になるのでお奨めしません。
(Form3 を閉じる前には、Form2 の Owner を Form3 から Form1 に戻す処理も必要)
投稿者 さしみマン  (社会人) 投稿日時 2021/11/10 17:33:28
ご返信ありがとうございます。

>複数のフォームを触れるようにしたいのであれば、そもそもモーダルを選択すべきでは無いと思いますよ。

おっしゃる通りだと思います。
私の説明の仕方が悪かったのですが、元々「form1」にはモーダルのみでした。
ただ、モーダルを実装した後に、「モーダルが出ていても触れるフォーム」を作成することになりました。

----フォーム「form1」のコード---- ↓わかりづらくてすいません。モーダルが先です。
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Form2.ShowDialog() 
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
   Form3.Show()   
    End Sub


ですので、モーダルをモーダレスのものに変更することは出来ないです。

投稿者 魔界の仮面弁士  (社会人) 投稿日時 2021/11/10 18:05:01
> 元々「form1」にはモーダルのみでした。
済みません。『Form1 にはモーダルのみ』という日本語の意味が分かりません。

元々 Form2 や Form3 はなく、Form1 のみをモーダルで表示していた、という意味でしょうか?

Form1 をスタートアップフォームとしていた場合、通常は、
暗黙の Application.Run メソッドによって起動されますが、
それを意図的に、Sub Main() から ShowDialog で呼び出していたとか。

それとも、ここでいう Form1 とは、フォーム名ではなくプロジェクト名なのでしょうか?
(Form1.exe が扱うフォームがすべてモーダルだった、という意味で)


なお、ShowDialog で呼び出したフォームは、Close メソッドを呼び出したり
右上の × を押したとしても、非表示になるだけでメモリ上には残ったままになります。
そのため Show メソッドで呼んだ場合とは異なり、呼び出し元が責任をもって
モーダルフォームを Dispose すう必要があることも忘れずに…。
https://dobon.net/vb/bbs/log3-42/25503.html


> モーダルをモーダレスのものに変更することは出来ないです。
モーダレスではなく、モードレスですね。

アプリケーションの仕様を変更することは出来ないと言っても、
Windows の動作仕様を変更することはもっと出来ないことなので、
正攻法としては、やはり下記のいずれかになろうかと思います。

案1) アプリケーションをモードレスに修正する
案2) モードレスを一時的に Hide して、モーダルの Shown イベントで表示しなおす


モーダルフォーム上から、モードレスフォームを表示することは可能ですが、
モーダルからモードレスに切り替えることはできないので、そのフォームは
Close なり Hide なり Visible = False なりで一度閉じてから開きなおす必要があります。
これが案2の手法にあたります。

ただし、そのフォームを Owner とする子フォームがいた場合、親が閉じられた(非表示も含む)時に
子フォームも連鎖して閉じられることになる点を考慮する必要があります。

案2 だと、フォーム間の依存関係が強くなり、手間も増えるので、
個人的には 案1 への移行を検討することをお奨めしておきます。