|
■No86479 (Yukihiko さん) に返信 > 9 番目の NumericUpDown で Tab キーまたは Enter キーをおすとフォーカスが消え、 > もう一度 Tab キーまたは Enter キーを押すと一番目の NumericUpDwn にフォーカスが戻ります。
消えたのではなく、何か別のコントロールにフォーカスがある状態なのだと思います。
それが何であるかを確認するため、以下のことを試してみてください。 フォーカスが移動すると、フォームのタイトルにそのコントロールの名前が表示されるようになります。
========================== (1) ツールボックスから "Timer" を探し、それをフォームに貼ります。
(2) フォームの Load イベントに以下のコードを記述し、タイマーを有効にします。
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load '0.5秒間隔で監視する Timer1.Interval = 500 Timer1.Start() End Sub
(3) フォームに貼った Timer コンポーネントをダブルクリックするなどしてコードエディタを開き、 Timer の Tick イベントを以下のように記述します。
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick If Me.ActiveControl Is Nothing Then Me.Text = "フォーカスなし" Else Me.Text = TypeName(Me.ActiveControl) & "/" & Me.ActiveControl.Name End If End Sub
(4) プログラムを実行し、9 番目の NumericUpDown で Tab キーを押して、フォームタイトルを確認します。 ==========================
> 9 番目の NumericUpDown からすぐに 1 番目の NumericUpDown にフォーカスを移動させるには、 > どの様にしたら良いでしょうか ? なお、NumericUpDown は TabPage に貼り付けてあります。
恐らくは TabControl にフォーカスが移動しているのだと思います。 その TabPage の親となる TabControl の TabStop プロパティを False にすることで 状況が変わってくるかもしれません。
> Private Sub Numericupdown_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) Handles NumericUpDown2.KeyPress > Private Sub Numericupdown_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) Handles NumericUpDown4.KeyPress
『Numericupdown_KeyPress』が 2 回登場していますね。 名前と引数定義が同一な定義を複数回記述することは出来ません。
このような場合には、それぞれのイベントハンドラーに対して、
Private Sub NumericUpDown2_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) Handles NumericUpDown2.KeyPress Private Sub NumericUpDown4_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) Handles NumericUpDown4.KeyPress
のように、それぞれに別の名前を割り当てるようにするか、もしくは、
Private Sub NumericUpDowns_KeyPress(ByVal sender As NumericUpDown, ByVal e As KeyPressEventArgs) Handles NumericUpDown2.KeyPress, NumericUpDown4.KeyPress
のように、一つのイベントハンドラーに対して、複数のイベントをまとめて割り当てるようにします。 後者のようにまとめた場合には、実行時に引数 sender を調べることで、NumericUpDown2 と NumericUpDown4 の いずれのイベントが発生しているのかを区別することが出来ます。
> If ((e.KeyChar = ControlChars.Cr) Or (e.KeyChar = ControlChars.Tab)) Then
「Or」ではなく、短絡評価となる「OrElse」を使うようにしましょう。
> NumericUpzDown1 との合計値が 1800 を越えた場合
越ではなく超な気もしますが、それはさておき。
> 2. NumericUpDown2 で NumericUpzDown1 との合計値が 1800 を越えた場合、MessageBox でエラーを表示しています。
NumeriUpDown1 が 0 のまま、NumericUpDown2 に 1800 と入力した後で NumeriUpDown1 に戻り(合計1800)、 NumeriUpDown1 の値を 0 から 1 に変更して Enter した場合(合計1801)は、警告しなくて良いのですか?
> 同様に、NumericUpDown4 でも NumericUpDown1 から 4 の合計値が 1800 を越えた場合に messageBox で同じように > エラーを表維持したいのですが、コンパイルエラーとなってしまいます。
そもそも、検出手順に問題があるように思えます。上記でも例示したように、ユーザーが必ずしも、 NumericUpDown1〜9 を順番に入力するとは限らないことを念頭に設計した方が良いのではないでしょうか。
たとえば NumericUpDown1 に「980」 NumericUpDown2 に「760」 NumericUpDown3 に「50」 まで入力した場合、ここまでの合計は 1790 ですよね。
ここで NumericUpDown3 の上で Enter も Tab も押さず、代わりに 【Shift+Tab】を押して NumericUpDown2 に戻ったとします。
そして NumericUpDown2 を「800」 に変更し、さらに、NumericUpDown2 の上で Enter も Tab も押さず、 NumericUpDown4 を【クリック】したとします。
この場合、KeyDown イベントの処理を通過しないので、1800 超過の判定が行われません。 その結果、NumericUpDown4 にフォーカスが遷移した時点で NumericUpDown1 に「980」 NumericUpDown2 に「800」 NumericUpDown3 に「50」 NumericUpDown4 は初期値(たとえば 0) ということで、警告されることなく、合計 1830 に到達してしまうことになります。
> この解決策をお教え下さい。
これで如何でしょうか。 ツールボックスから "ErrorProvider" を貼っておいてください。
※NumbericUpDown1〜4 のみ。5〜9 の処理は省略しています。
Imports System.ComponentModel
Public Class Form1 Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles MyBase.KeyDown If e.KeyCode = Keys.Enter Then SelectNextControl(ActiveControl, Not e.Shift, True, True, True) e.Handled = True End If End Sub
Private Sub NumericUpDowns_ValueChanged(sender As NumericUpDown, e As EventArgs) Handles _ NumericUpDown1.ValueChanged, NumericUpDown2.ValueChanged, NumericUpDown3.ValueChanged, NumericUpDown4.ValueChanged
ErrorProvider1.Clear() Dim total As Decimal = NumericUpDown1.Value + NumericUpDown2.Value + NumericUpDown3.Value + NumericUpDown4.Value If total > 1800D Then ErrorProvider1.SetError(sender, "合計値が 30 分を越えています。") End If End Sub
Private Sub NumericUpDowns_Validating(sender As NumericUpDown, e As CancelEventArgs) Handles _ NumericUpDown1.Validating, NumericUpDown2.Validating, NumericUpDown3.Validating, NumericUpDown4.Validating
Dim total As Decimal = NumericUpDown1.Value + NumericUpDown2.Value + NumericUpDown3.Value + NumericUpDown4.Value If total > 1800D Then e.Cancel = True Dim ms As String = CStr(total \ 60D) & "分" & CStr(total Mod 60D) & "秒" MessageBox.Show("合計値が 30 分を越えています。(" & ms & ")", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning) End If End Sub End Class
|