投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/12/13 17:25:36
> 昨夜、そのボタンの DialogResult プロパティの変更を試行いたしました時には
> 元々の None 以外の何を選択してもエラーになってデバッグそのものが進行できませんでした。

恐らくは、デバッグ実行中に(実行を停止させずに)デザイン画面を変更したのではないでしょうか?
その場合「プロパティの値が無効です。」のエラーになりますので。
※エラーの詳細を見ると、「ビルド中またはデバッグ中に、ファイル {何某} をデザイナーで変更することはできません。」と表示される状況です。


もしも固定的に OK を返すだけで良いのであれば、今回の場合は
Form2 の Button1 の DialogResult を OK にするだけで充分です。

キーボードでの操作を含めたいなら、そのボタンの PerformClick メソッドを呼ぶことで
ボタンのクリック操作をエミュレートできます。例えばこのように書きます。
MouseUp イベントも不要ですし Close メソッドも要りません。

Public Class Form2
    Private Sub Button1_PreviewKeyDown(sender As Button, e As PreviewKeyDownEventArgs) Handles Button1.PreviewKeyDown
        Static KeyList As Keys() = {Keys.Enter, Keys.Space, Keys.H, Keys.Tab, Keys.Space, Keys.F12}
        If KeyList.Contains(e.KeyCode) Then
            sender.PerformClick()
        End If
    End Sub
End Class


常に OK を返すのではなく、条件によって戻り値を変更したい場合には、
Button1 の DialogResult は何でも良い(None でも良い)ので、
Button1 の Click イベント内で、条件に応じて Me.DialogResult を切り替えるようにします。
この場合は PreviewKeyDown の実装は変えずに、単に PerformClick するだけです。



> ① エンターキーが返す値は、そのボタンの DialogResult プロパティの値。
>  ただし、None の時は何も返さない。

Button1 をクリックすれば、Button1.DialogResult が Me.DialogResult に伝播するということです。
実行時の Button1.DialogResult が None なら、Me.DialogResult は None のままで閉じられません。


今回は Enter キーが問題になりましたが、Escape キーでも特殊な動作が発生する可能性があります。
具体的には、Form2 の【CancelButton プロパティ】に Button1 を割り当てていたようなケースです。
CancelButton を割りあてておくと、Esc キーを押したときに、そのボタンのクリック動作が発生します。

【CancelButton プロパティ】に Button1 を割り当てた時点で、
Button1 の DialogResult は Cancel に自動設定されます。
(後から Cancel 以外に変更することもできますが、デザイナ上で None に設定した場合、実行時には Cancel になるのでご注意ください)



さて、Button1 の DialogResult が戻り値として伝播するのは、マウスでクリックしたときだけではありません。
今回問題になった、いわゆる「ダイアログキー」による操作でも伝播します。

ボタンがアクティブな状態での Enter キーや
AcceptButton が設定されているときの Enter キーや
CancelButton が設定されているときの Esc キーのことです。

その結果、Button1_PreviewKeyDown で「If e.KeyCode = Keys.何某 Then」判定にて
Me.DialogResult を書き換えても、既定の Enter キーの動作(CencelButton なら Esc キーも)は継続して処理され、
実行時の Button1.DialogResult が、Me.DialogResult に上書きされることになります。

もしも PreviewKeyDown の処理後に、この既定の動作をスキップさせたい場合には、
ダイアログキーの処理を無効化するために、ProcessDialogKey メソッドをオーバーライドします。

Private SkipDialogKey As Boolean = False
Private Sub Button1_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles Button1.PreviewKeyDown
    If e.KeyCode = Keys.何某 Then
        SkipDialogKey = True
        Me.DialogResult = 任意
    End If
End Sub
Protected Overrides Function ProcessDialogKey(keyData As Keys) As Boolean
    If SkipDialogKey Then
        Return False
    Else
        Return MyBase.ProcessDialogKey(keyData)
    End If
End Function


なお、Tab キーや矢印キーもダイアログキーの一種です。にもかかわらず「e.KeyCode = Keys.Tab」の時に
問題が起きなかったのは、Tab キーは Button のクリック動作を引き起こすものではないためです。



> ② そのほかのキーが返す値は、Me.DialogResult = DialogResult.○✕ で書いた○✕の値。
> ○✕が None の時は、Cancel を返す。

DialogResult が未設定のまま閉じられた場合は、Cancel とみなす設計になっています。
これは先の回答でいうところの
>> ★現在値が None の状態で下記が行われると Cancel になり、ダイアログは閉じられます。
にあたります。

たとえば YesNo タイプや AbortRetryIgnore タイプのメッセージボックスの場合、
右上の ×ボタンが意図的に使えなくなっていますが、これも同様の理由によるものです。
(ボタンを選ばなかった時の戻り値がキャンセルになってしまうことを防ぐため)

キャンセルをボタンを持つメッセージボックスであれば、右上の×ボタンが使えます。

なお、OK しかないメッセージボックスの場合は単一選択なので、
×ボタンを押しても Ok 扱いになる設計になっています。ですからダイアログを自作する場合は、
そのダイアログが×ボタンやタスクマネージャーで閉じられたときに、
何を返すように設計すべきかを検討しておきましょう。