C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

テキストボックスでEnter キーを押した場合のプログラミン

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■86368 / inTopicNo.1)  テキストボックスでEnter キーを押した場合のプログラミン
  
□投稿者/ Yukihiko (15回)-(2018/01/23(Tue) 13:53:02)

分類:[VB.NET/VB2005 以降] 

開発環境: VisualBasic 2010
OS: windows 10 64 ビット

画面上に 3 のテキストボックス TxtBox1、TxtBox2、TxtBox3 があり、フォーカスが TxtBox2 にあるとき、Enter キーを押すと TxtBox1 の内容と TxtBox2 の内容を加算し、ある一定値以上だとエラーと見なして、TxtBox1、TxtBox2 の内容をクリアーしてフォーカスを TxtBox1 に移動させたいのです。なお、条件を満たした場合は、TxtBox3 にフォーカスを移動させたいですが、プログラミングの方法が解りません。どなたかお教え頂ければ幸いです。
引用返信 編集キー/
■86369 / inTopicNo.2)  Re[1]: テキストボックスでEnter キーを押した場合のプログラミン
□投稿者/ WebSurfer (1415回)-(2018/01/23(Tue) 13:57:20)
No86368 (Yukihiko さん) に返信

何を作っているか(Windows Forms? ASP.NET Web Forms? ASP.NET MVC? WPF? その他?)を質問の一番
最初に書きましょう。
引用返信 編集キー/
■86371 / inTopicNo.3)  Re[1]: テキストボックスでEnter キーを押した場合のプログラミン
□投稿者/ 魔界の仮面弁士 (1547回)-(2018/01/23(Tue) 15:04:31)
No86368 (Yukihiko さん) に返信
> 画面上に 3 のテキストボックス TxtBox1、TxtBox2、TxtBox3 があり、
> フォーカスが TxtBox2 にあるとき、Enter キーを押すと

TextBox1 で Enter を押したときは、特に何もしなくて良いのですね?


> TxtBox1 の内容と TxtBox2 の内容を加算し、

加算を行うには、入力内容が「数値」であることを保証しなければいけませんね。

数値入力に特化させるのであれば、
TextBox の Text プロパティの代わりに
NumericUpDown の Value プロパティを使うのが簡単です。
(Windows フォームアプリケーション の場合)

NumericUpDown を使えば、数値以外が入力されることを防げますし、
最大値(Maximum)、最小値(Minimum)、小数点以下の桁数(DecimalPlaces)も
指定しておくこともできるので、プログラミングの手間が省けます。


どうしても TextBox を使いたいのであれば、
追加の入力検査処理が必要になってきます。

 'TextBox の内容を数値として受け取るための変数
 Dim a, b As Decimal
 
 If Decimal.TryParse(TextBox1.Text, a) AndAlso _
   Decimal.TryParse(TextBox2.Text, b) Then
   '
   'TextBox1、TextBox2 の両方共に数値が入力されていた
   '
   Dim c As Decimal = a + b '両者を加算
   '
   '(加算した結果を表示・加工・判定するための処理をここに記述)
   '
 Else
   '
   '非数値が入力されていた
   '
 End If



> ある一定値以上だとエラーと見なして、
> TxtBox1、TxtBox2 の内容をクリアーして

範囲外の値が入力された場合、エラーであることを
ユーザーに(色やメッセージなどで)一切伝えずに
いきなりクリアしてしまってよいのですか?


> フォーカスを TxtBox1 に移動させたいのです。
> 条件を満たした場合は、TxtBox3 にフォーカスを移動させたい

条件を満たしているかどうかを If 文で判断した上で、
  TextBox1.Focus()
のようにすれば、フォーカスが移動できます。
フォーカスの移動については、ここの掲示板のサンプルにも記載されていますね。
http://jeanne.wankuma.com/tips/vb.net/control/focus.html


> プログラミングの方法が解りません。

どこまで分かっていて、どの部分で詰まっているのかを明確にしてもらえると回答しやすいです。

たとえば Enter キーが押された時に、何か追加の処理を行いたいのであれば、このように書けます。

Private Sub TextBox2_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextBox2.KeyPress
 If e.KeyChar = ControlChars.Cr Then
  e.Handled = True
  '
  '
  'Enter が押された時の処理をここに記述
  '
  '
 End If
End Sub
引用返信 編集キー/
■86479 / inTopicNo.4)  Re[2]: テキストボックスでEnter キーを押した場合のプログラミン
□投稿者/ Yukihiko (16回)-(2018/02/02(Fri) 10:40:34)
No86371 (魔界の仮面弁士 さん) に返信
魔界の仮面弁士さま、詳しい解説有り難う御座いました。いろいろと勉強になりました。
その後、二つほど、疑問が御座いますのでお教えを賜りたく思います。

1. NumericUpDown を 9 個画面に貼り付け、TabStop プロパティを True としました。このとき、Tab キーおよび Enter キーでフォーカスは移動するのですが、9 番目の NumericUpDown で Tab キーまたは Enter キーをおすとフォーカスが消え、もう一度 Tab キーまたは Enter キーを押すと一番目の NumericUpDwn にフォーカスが戻ります。9 番目の NumericUpDown からすぐに 1 番目の
NumericUpDown にフォーカスを移動させるには、どの様にしたら良いでしょうか ? なお、NumericUpDown は TabPage に貼り付けてあります。

2. NumericUpDown2 で NumericUpzDown1 との合計値が 1800 を越えた場合、MessageBox でエラーを表示しています。同様に、NumericUpDown4 でも NumericUpDown1 から 4 の合計値が 1800 を越えた場合に messageBox で同じようにエラーを表維持したいのですが、コンパイルエラーとなってしまいます。この解決策をお教え下さい。

プログラムを以下に示します。

Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
If (e.KeyCode = Keys.Enter) Then
Dim forward As Boolean = e.Modifiers <> Keys.Shift

Me.SelectNextControl(Me.ActiveControl, forward, True, True, True)
e.Handled = True
End If

End Sub

Private Sub Numericupdown_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) Handles NumericUpDown2.KeyPress
If ((e.KeyChar = ControlChars.Cr) Or (e.KeyChar = ControlChars.Tab)) Then
e.Handled = True
Dim Ret As DialogResult

If (NumericUpDown1.Value + NumericUpDown2.Value > 1800) Then
Ret = MessageBox.Show("1st Start Time と 1st Control Time の合計値が 30 分を越えています。", _
"警告", MessageBoxButtons.OK, MessageBoxIcon.Warning)
NumericUpDown1.Value = 0
NumericUpDown2.Value = 0
NumericUpDown1.Focus()
End If
End If
End Sub
'このロジックを追加すると上のサブルーチンでエラーとなります。
Private Sub Numericupdown_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) Handles NumericUpDown4.KeyPress
If ((e.KeyChar = ControlChars.Cr) Or (e.KeyChar = ControlChars.Tab)) Then
e.Handled = True
Dim Ret As DialogResult

If (NumericUpDown1.Value + NumericUpDown2.Value + NumericUpDown3.Value + NumericUpDown4.Value > 1800) Then
Ret = MessageBox.Show("1st Start Time から 2nd ControlTime までの合計値が 30 分を越えています。", _
"警告", MessageBoxButtons.OK, MessageBoxIcon.Warning)
NumericUpDown1.Value = 0
NumericUpDown2.Value = 0
NumericUpDown1.Focus()
End If
End If
End Sub

以上、宜しくお願い致します。
引用返信 編集キー/
■86480 / inTopicNo.5)  Re[3]: テキストボックスでEnter キーを押した場合のプログラミン
□投稿者/ 魔界の仮面弁士 (1562回)-(2018/02/02(Fri) 12:26:21)
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
引用返信 編集キー/
■86807 / inTopicNo.6)  Re[4]: テキストボックスでEnter キーを押した場合のプログラミン
□投稿者/ Yukihiko (17回)-(2018/03/19(Mon) 13:08:04)
No86480 (魔界の仮面弁士 さん) に返信
> ■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

魔界の仮面弁士さま、お教え下さって有り難う御座います。病を得てしばらく書き込みが出来なかったことをお詫び申し上げます。問題は、解決致しました。ご丁寧な解説、有り難う御座いました。今後とも宜しくお願い致します。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ