投稿者 魔界の仮面弁士  (社会人) 投稿日時 2018/5/24 04:52:12
kkkkk さんと uuu さんは同じ方でしょうか?
別の質問とはいえ、内容が酷似しているようなので。


> 教えていただいた
> If a > b AndAlso b > c Then
> は a>cも含まれているでしょうか?

はい。たとえば a, b, c いずれもが Integer 値だとすれば、
a > b かつ b > c であるにも関わらず、
a > c にならない(つまり a ≦ c である)ような数はありえませんよね。

数学的に言えば、 (a > b) ∧ (b > c) の関係を意味しますので、
それが (a > c) の関係であることも自明となります。


厳密に言ってしまえば、言語仕様的には
 If a > b AndAlso b > c AndAlso a > c Then
 If a > b AndAlso b > c Then
の 2 つの結果が異なる結果になることも、一応ありえなくはなかったりします。
とはいえそれは非常に特殊なケースに限られますので、
通常はそこまで考えなくて良いでしょう。


> If Val(TextBox2.Text) > Val(TextBox1.Text) Then
Val の利用はおすすめしません。(エラーになりえるので)

せっかく TryParse メソッドを利用しているのですから、
それで変換した値を使うべきでしょう。


> 対策として下記で対応しているんですけど、問題はありませんか?
問題があると思いますよ。

強制的にフォーカスを当てなおしているのが、あまり良くないですが、
それ以上に、テキストの内容が『』や『XYZ』や『0』や『-123』だった場合の
処置が抜けているのが問題ですし、sender と TextBox1~3 の組み合わせも不自然です。


また、a, b, c の 3 個所のうち、2 個所の修正が必要な場合において、
そのうちの 1 個所を編集すると、一時的に大小関係が崩れてしまい、
2 個所目の編集が始められないといったパターンが起こりそうです。


極端な話、初期状態でのフォーカス位置と TextBox の値が下記のようになっていた場合、
提示頂いたコードだと、a(TextBox1) と b(TextBox2) の比較でメッセージが表示されるのに、
それとは無関係のはずの c(TextBox3)が赤くなり、a や b を訂正しようとしても
阻害されてしまうことになると思います。

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    For Each q In Me.Controls.OfType(Of TextBox)()
        AddHandler q.Leave, AddressOf TextBoxes_Leave
    Next
    TextBox1.Text = "10"
    TextBox2.Text = "20"
    TextBox3.Text = "30"
    ActiveControl = TextBox3
End Sub



そもそも、今回の仕様が
・どういう時に赤くなってほしいのか
・赤から標準色に戻すのはどういう時か
・Leave したコントロール以外が赤になってほしいパターンがあるのか
・Leave したコントロール以外を標準色に戻したいパターンがあるのか
・「空欄時」「非数値の時」「マイナス値の時」「0 の時」とで、対処を変える必要があるのか否か
などが曖昧なので、どういう動作を求めているのかを、
より細かく確認しなおすのが先決かと思います。


> またテキストボックスに入力時に3つの関係が不適切ならメッセージを出すようにしたいです。

「3 つの関係」を調査しなければならないのに、1 つのボックスの Leave 時に
即時検査する画面設計にしているのが、話を複雑化しているように思います。

こういう場合には、入力後即時に検査するのではなく、値を確定するタイミングを
後回しにするという手法が良く利用されます。

たとえば、ファイルを右クリックしてプロパティを表示させた場合、
[全般]タブでファイル名を変更できるようになっていますが、ここで、
ファイル名のテキストボックスを空にしたり、ファイル名として利用できない文字を
入力したとしても、それだけでは直ちにエラーメッセージが表示されることはありません。

この場合、ファイル名の入力値検査は、プロパティ ダイアログの
[OK]ボタンを押したタイミングで行われるようになっています。


なのでそれを真似て、Leave 時あるいは Validating 時に検査するのは、
「現在のボックスに正数がセットされたか」のみに限定してしまい、
各ボックスの大小判定は、ボタンクリック時などといった
別のタイミングで検証した方が良いのではないでしょうか。


仮に、ユーザー入力の問題をその場で指摘した方がよい仕様だったとしても、
モーダルのメッセージなどを用いるのではなく、こういう場合には
インプレースエラー表示(たとえば ErrorProvider を利用した表現)や、
モードレスのエラー処理(たとえば Tooltip のバルーンモード) の利用を
検討した方が、うまくいくかもしれません。
https://msdn.microsoft.com/ja-jp/library/aa511267.aspx#presentation

MsgBox などといったモーダルのエラー処理を行うと、エラーメッセージを閉じるまで、
値の再入力ができなくなるので、連続した入力を阻害する結果になりえます。