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

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

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

テキストボックスの入力値の制限方法について

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

■93933 / inTopicNo.1)  テキストボックスの入力値の制限方法について
  
□投稿者/ yuji (1回)-(2020/02/22(Sat) 19:28:26)

分類:[.NET 全般] 

vb2010/windows7
windowsフォームで通信系のアプリを作成しています。
フォームに用意したテキストボックスへの入力値を
16進数の0〜9とa〜fのみ入力できるようにしたいのですが
方法がわからないのでご教授願います。
引用返信 編集キー/
■93934 / inTopicNo.2)  Re[1]: テキストボックスの入力値の制限方法について
□投稿者/ Azulean (1134回)-(2020/02/22(Sat) 20:16:45)
No93933 (yuji さん) に返信
> vb2010/windows7
> フォームに用意したテキストボックスへの入力値を
> 16進数の0〜9とa〜fのみ入力できるようにしたいのですが
> 方法がわからないのでご教授願います。

ここの記事を読んで応用すれば作れる範囲ではありますが、どの程度、頑張れそうですか?
https://dobon.net/vb/dotnet/control/numerictextbox.html
引用返信 編集キー/
■93936 / inTopicNo.3)  Re[1]: テキストボックスの入力値の制限方法について
□投稿者/ 魔界の仮面弁士 (2566回)-(2020/02/23(Sun) 13:28:58)
No93933 (yuji さん) に返信
> フォームに用意したテキストボックスへの入力値を
> 16進数の0〜9とa〜fのみ入力できるようにしたいのですが

TextBox の代わりに NumericUpDown コントロールを使うのは如何でしょうか。

 Hexadecimal = True '16進数モード
 DecimalPlaces = 0 '小数桁なし
 Increment = 1
 Minimum = 0
 Maximum = 任意
 TextAlgin = 任意
引用返信 編集キー/
■93940 / inTopicNo.4)  Re[2]: テキストボックスの入力値の制限方法について
□投稿者/ yuji (2回)-(2020/02/23(Sun) 16:27:17)
No93934 (Azulean さん) に返信
返信ありがとうございます。
記事を参考にし、MaskedTextBoxコントロールでKeyPressイベントを使って Me.MaskedTextBox1.Mask = "9999"として
試してみたところテキストボックスに"1234"などの数値が入力できることはわかりました。
また、MaskedTextBoxコントロールでKeyDownイベントを使ってMe.MaskedTextBox1.Mask = "????"として
If (e.KeyCode = Keys.A Or Keys.B Or Keys.C Or Keys.D Or Keys.E Or Keys.F)で
試してみましたがテキストボックスの入力値がa〜f以外の文字の場合でも入力できてしまいます。

a〜fまでの文字のみ入力できるようにする方法と"0A2C"などのように文字と数字が混ざっているような場合に
入力できるようにする方法がわかりません。



■93936 (魔界の仮面弁士 さん)に返信
返信ありがとうございます。
マウスでのスクロール操作ができないようにしたいため、ほかの方法かもしくは
NumericUpDown コントロールでマウスでのスクロール操作ができないようにする方法はありませんか?


ご教授願います。
引用返信 編集キー/
■93941 / inTopicNo.5)  Re[3]: テキストボックスの入力値の制限方法について
□投稿者/ Azulean (1135回)-(2020/02/23(Sun) 19:22:18)
2020/02/23(Sun) 19:39:12 編集(投稿者)

No93940 (yuji さん) に返信
> 記事を参考にし、MaskedTextBoxコントロールでKeyPressイベントを使って Me.MaskedTextBox1.Mask = "9999"として
> 試してみたところテキストボックスに"1234"などの数値が入力できることはわかりました。

なぜ組み合わせたのかわかりませんが、MaskTextBox は特定の文字・書式を強制するためのコントロールです。
このため、そのコントロールで、KeyPress/KeyDown イベントと組み合わせて入力制限するのは「変」です。

> また、MaskedTextBoxコントロールでKeyDownイベントを使ってMe.MaskedTextBox1.Mask = "????"として
> If (e.KeyCode = Keys.A Or Keys.B Or Keys.C Or Keys.D Or Keys.E Or Keys.F)で
> 試してみましたがテキストボックスの入力値がa〜f以外の文字の場合でも入力できてしまいます。

ん?
「e.KeyCode = Keys.A Or Keys.B Or Keys.C Or Keys.D Or Keys.E Or Keys.F」は「KeyCode が A 〜 F のいずれか」ではありません。
この場合、常に True になるんじゃないかなぁ…。


この If 文は「e.KeyCode = Keys.A」「Keys.B」「Keys.C」「Keys.D」「Keys.E」「Keys.F」という区切りに対して Or で結合されている。
なので、e.KeyCode の値をチェックしているのは「e.KeyCode = Keys.A」だけ。
どんなキーでも OK となってしまうのは、「Keys.B」などが「True」と扱われるから。
やりたいことは「e.KeyCode = Keys.B」(以下略)のはずなので、正しく書かないといけません。
このあたりが理解できないと今後つらいかも…。

とりあえず、「e.KeyCode が Keys.0 〜 Keys.9 のいずれか」と「e.KeyCode が Keys.A 〜 Keys.F のいずれか」の Or でないといけないので、VB.NET の If 文の書き方をいろいろと調べてみてください。


ところで、a 〜 f と、A 〜 F は文字としては別物ですので、「文字」として判定する方法を採用する場合は気をつけてください。
KeyCode の場合は気にしなくて良いと思います。
引用返信 編集キー/
■93943 / inTopicNo.6)  Re[1]: テキストボックスの入力値の制限方法について
□投稿者/ KOZ (86回)-(2020/02/23(Sun) 23:14:25)
2020/02/24(Mon) 20:36:18 編集(投稿者)
No93933 (yuji さん) に返信
> フォームに用意したテキストボックスへの入力値を
> 16進数の0〜9とa〜fのみ入力できるようにしたいのですが
> 方法がわからないのでご教授願います。

こんな感じでカスタムコントロールを作っては?

Public Class HexadecimalTextBox
    Inherits TextBox

    Private Const WM_PASTE As Integer = &H302

    Private Shared CTRL_BASE As Integer = AscW("A"c) - 1
    Private Shared CTRL_A As Char = ChrW(AscW("A"c) - CTRL_BASE)
    Private Shared CTRL_C As Char = ChrW(AscW("C"c) - CTRL_BASE)
    Private Shared CTRL_V As Char = ChrW(AscW("V"c) - CTRL_BASE)
    Private Shared CTRL_X As Char = ChrW(AscW("X"c) - CTRL_BASE)
    Private Shared CTRL_Z As Char = ChrW(AscW("Z"c) - CTRL_BASE)

    Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)
        Select Case e.KeyChar
            Case CTRL_A
                Me.SelectAll()
                e.Handled = True
            Case CTRL_C, CTRL_V, CTRL_X, CTRL_Z
            Case ControlChars.Back
            Case Else
                e.KeyChar = RestrictChar(e.KeyChar)
                e.Handled = (e.KeyChar = ChrW(0))
        End Select
        MyBase.OnKeyPress(e)
    End Sub

    Protected Overridable Function RestrictChar(c As Char) As Char
        Select Case c
            Case "0"c To "9"c, "a"c To "f"c
                Return c
            Case "A"c To "F"c
                Return Char.ToLower(c)
            Case Else
                Return ChrW(0)
        End Select
    End Function

    Protected Overrides Sub WndProc(ByRef m As Message)
        Select Case m.Msg
            Case WM_PASTE
                If Clipboard.ContainsText() Then
                    Dim sb As New Text.StringBuilder()
                    Dim pasteMaxLength As Integer
                    If MaxLength > 0 Then
                        pasteMaxLength = MaxLength - TextLength + SelectionLength
                    Else
                        pasteMaxLength = Integer.MaxValue - TextLength + SelectionLength
                    End If
                    For Each c As Char In Clipboard.GetText()
                        If sb.Length >= pasteMaxLength Then
                            Exit For
                        End If
                        Dim rc As Char = RestrictChar(c)
                        If rc <> ChrW(0) Then
                            sb.Append(rc)
                        End If
                    Next
                    MyBase.Paste(sb.ToString())
                End If
            Case Else
                MyBase.WndProc(m)
        End Select
    End Sub

End Class

引用返信 編集キー/
■93945 / inTopicNo.7)  Re[4]: テキストボックスの入力値の制限方法について
□投稿者/ 魔界の仮面弁士 (2569回)-(2020/02/24(Mon) 11:38:58)
No93941 (Azulean さん) に返信
>> If (e.KeyCode = Keys.A Or Keys.B Or Keys.C Or Keys.D Or Keys.E Or Keys.F)で
> この If 文は「e.KeyCode = Keys.A」「Keys.B」「Keys.C」「Keys.D」「Keys.E」「Keys.F」という区切りに対して Or で結合されている。
> なので、e.KeyCode の値をチェックしているのは「e.KeyCode = Keys.A」だけ。
> どんなキーでも OK となってしまうのは、「Keys.B」などが「True」と扱われるから。

上記の説明だと、ここの型変換が
 If (e.KeyCode = Keys.A) Or CBool(Keys.B) Or CBool(Keys.C) Or CBool(Keys.D) Or CBool(Keys.E) Or CBool(Keys.F) Then
と解釈されているかのようにも読めてしまうので、少し補足。

この場合、実際の判定処理は
 If CBool(CInt(e.KeyCode = Keys.A) Or CInt(Keys.B) Or CInt(Keys.C) Or CInt(Keys.D) Or CInt(Keys.E) Or CInt(Keys.F)) Then
に相当する形で行われることになります。

最初に = 演算子が判定されて Boolean 値になりますが、
「Boolean値 Or Keys列挙値」の演算結果は、Integer 値として扱われるためです。

Dim x = Keys.A Or Keys.B 'x は Keys 型になる
Dim y = True Or Keys.B 'y は Integer 型になる
Dim z = True OrElse Keys.B 'z は Boolean 型になる

そして Integer が Boolean に変換される場合、0 以外はすべて True 相当と解釈されます。
(Keys が Boolean に変換される場合は、Keys.None 以外すべて True 相当と解釈されます)

それゆえに yuji さんの If 文だと、e.KeyCode の値が Keys.A であろうとなかろうと、
If 判定がすべて True 扱いになってしまいますね。


> ■93936 (魔界の仮面弁士 さん)に返信
> NumericUpDown コントロールでマウスでのスクロール操作ができないようにする方法はありませんか?

スクロールというのは、ホイール操作のことでしょうか。
だとしたら、Increment を 0 にすれば、ホイール操作で値が変更されなくなりますよ。


もしも ▲▼ボタンは使えるようにしつつ、ホイール操作は無効化したい場合には、
NumericUpDown を継承して、OnMouseWheel メソッドの呼び出しを握りつぶすことで対処できます。

なお、ボタンその物を消す方法は用意されていません。
『NumericUpDown1.Controls(0).Hide()』などで無理矢理隠すことはできますが、
そこまで大きく変更する場合は、NumericUpDown 以外の方法を使った方が良いですね。


No93933 (yuji さん) に返信
> フォームに用意したテキストボックスへの入力値を
> 16進数の0〜9とa〜fのみ入力できるようにしたいのですが

A〜F なら良いですが、a〜f を求めるとなると、NumericUpDown では無理がありますね…。

また、「通信系のアプリ」で扱う値の範囲が、Byte や Integer 値などであるならば、
NumericUpDown が便利だと思いますが、「先頭 0 埋めの固定長データ」や
「ASCII 文字列」などのバイナリ表現のために用いる場合には不向きです。

何故なら NumericUpDown の性質上、最大値が Decimal.MaxValue までと定められているためです。
FFFFFFFFFFFFFFFFFFFFFFFF(10 進数で「79,228,162,514,264,337,593,543,950,335」)以下の値しか扱えません。
しかも Hexadecimal モードになれば、Int64.MaxValue にまで限定されるため、
7FFFFFFFFFFFFFFF(10 進数で「9,223,372,036,854,775,807」)以下に制限されます。
引用返信 編集キー/
■93977 / inTopicNo.8)  Re[2]: テキストボックスの入力値の制限方法について
□投稿者/ yuji (3回)-(2020/02/28(Fri) 10:33:22)
No93943 (KOZ さん) に返信
> 2020/02/24(Mon) 20:36:18 編集(投稿者)
>
> ■No93933 (yuji さん) に返信
>>フォームに用意したテキストボックスへの入力値を
>>16進数の0〜9とa〜fのみ入力できるようにしたいのですが
>>方法がわからないのでご教授願います。
>
> こんな感じでカスタムコントロールを作っては?
>
> Public Class HexadecimalTextBox
> Inherits TextBox
>
> Private Const WM_PASTE As Integer = &H302
>
> Private Shared CTRL_BASE As Integer = AscW("A"c) - 1
> Private Shared CTRL_A As Char = ChrW(AscW("A"c) - CTRL_BASE)
> Private Shared CTRL_C As Char = ChrW(AscW("C"c) - CTRL_BASE)
> Private Shared CTRL_V As Char = ChrW(AscW("V"c) - CTRL_BASE)
> Private Shared CTRL_X As Char = ChrW(AscW("X"c) - CTRL_BASE)
> Private Shared CTRL_Z As Char = ChrW(AscW("Z"c) - CTRL_BASE)
>
> Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)
> Select Case e.KeyChar
> Case CTRL_A
> Me.SelectAll()
> e.Handled = True
> Case CTRL_C, CTRL_V, CTRL_X, CTRL_Z
> Case ControlChars.Back
> Case Else
> e.KeyChar = RestrictChar(e.KeyChar)
> e.Handled = (e.KeyChar = ChrW(0))
> End Select
> MyBase.OnKeyPress(e)
> End Sub
>
> Protected Overridable Function RestrictChar(c As Char) As Char
> Select Case c
> Case "0"c To "9"c, "a"c To "f"c
> Return c
> Case "A"c To "F"c
> Return Char.ToLower(c)
> Case Else
> Return ChrW(0)
> End Select
> End Function
>
> Protected Overrides Sub WndProc(ByRef m As Message)
> Select Case m.Msg
> Case WM_PASTE
> If Clipboard.ContainsText() Then
> Dim sb As New Text.StringBuilder()
> Dim pasteMaxLength As Integer
> If MaxLength > 0 Then
> pasteMaxLength = MaxLength - TextLength + SelectionLength
> Else
> pasteMaxLength = Integer.MaxValue - TextLength + SelectionLength
> End If
> For Each c As Char In Clipboard.GetText()
> If sb.Length >= pasteMaxLength Then
> Exit For
> End If
> Dim rc As Char = RestrictChar(c)
> If rc <> ChrW(0) Then
> sb.Append(rc)
> End If
> Next
> MyBase.Paste(sb.ToString())
> End If
> Case Else
> MyBase.WndProc(m)
> End Select
> End Sub
>
> End Class
>
解決済み
引用返信 編集キー/
■93983 / inTopicNo.9)  Re[3]: テキストボックスの入力値の制限方法について
□投稿者/ yuji (4回)-(2020/02/28(Fri) 16:43:48)
無事解決できました!

回答していただいたみなさんありがとうございました。
引用返信 編集キー/

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


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

このトピックに書きこむ