VB.NET数字または一部の文字しか入力できないようにする

スポンサーリンク

テキストボックスで数字または一部の文字しか入力できないようにするには、System.Windows.Forms.TextBox を継承したカスタム コントロールを使う方法が最も手軽です。

KeyPress イベントなどで入力を規制しているサンプルを良く見かけますが、あれでは「貼り付け」の対応ができません。少なくとも、コンテキスト メニューからの [貼り付け] は、キーの入力から排除できるものではありません。これを防ぐために TextChanged イベントと併用しているサンプルもありますが、あれではチラツキが生じます。

どのデバイスで入力されようと、一元で排除できるような機構にした方が楽なのです。だからといって 入力チェックをしなくても良いわけではない です。そういう意味でも、「最終チェックに一任する」という選択肢があることも忘れないでください。

実装方法ですが、先に申し上げたように System.Windows.Forms.TextBox クラスを継承したカスタム コントロールを作ります。ここで、WM_CHAR (クライアント領域への入力) と WM_PASTE (貼り付け) を捕捉し、然るべき処理を行えば良いのです。WM_CHAR と WM_PASTE を捕捉するために、WndProc メソッドをオーバーライドしています。

然るべき処理は、WndProc メソッドで実装せず、わかりやすくするために、OnChar メソッドと OnPaste メソッドを経ています。文字列を許可するかどうかの実際の判定は HasPermitChars 静的メソッドと、GetPermitedString 静的メソッドで実装しています。

サンプルなので、わかりやすくベタに実装しようかと思いましたが、少し汎用性を持たせたかったので、PermitChars プロパティを設けました。ここに格納された System.Char の配列が許可された文字になり、ここに登録されていない文字の入力はできなくなります。

まずは、カスタム コントロールを実装してみましょう。

サンプルコード

以下にサンプルコードを示します。

VB.NET 全般
Option Strict On

' 以下の名前空間をインポートする
Imports System.Windows.Forms

Public Class MyTextBox : Inherits System.Windows.Forms.TextBox

  #Region " コンストラクタ "

    Public Sub New()
        MyBase.New()
        Me.PermitChars = New Char() {}
    End Sub

  #End Region

  #Region " PermitChars プロパティ "

    Private _PermitChars As Char()

    Public Property PermitChars() As Char()
        Get
            Return Me._PermitChars
        End Get

        Set
            Me._PermitChars = Value
        End Set
    End Property

  #End Region

  #Region " WndProc メソッド (Overrides) "

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_CHAR  As Integer = &H0102
        Const WM_PASTE As Integer = &H0302

        Select Case m.Msg
            Case WM_CHAR
                Dim eKeyPress As New KeyPressEventArgs(Microsoft.VisualBasic.ChrW(m.WParam.ToInt32()))
                Me.OnChar(eKeyPress)

                If eKeyPress.Handled Then
                    Return
                End If
            Case WM_PASTE
                If (Not Me.PermitChars Is Nothing) AndAlso (Me.PermitChars.Length > 0) Then
                    Me.OnPaste(New System.EventArgs())
                    Return
                End If
        End Select

        MyBase.WndProc(m)
    End Sub

  #End Region

  #Region " OnChar メソッド (Overridable) "

    ' 文字列がクライアント領域に送信された時に呼び出されるメソッド
    Protected Overridable Sub OnChar(ByVal e As KeyPressEventArgs)
        If Char.IsControl(e.KeyChar) Then
            Return
        End If

        If Not HasPermitChars(e.KeyChar, Me.PermitChars) Then
            e.Handled = True
        End If
    End Sub

  #End Region

  #Region " OnPaste メソッド (Overridable) "

    ' [貼り付け] した時に呼び出されるメソッド
    Protected Overridable Sub OnPaste(ByVal e As System.EventArgs)
        Dim stString As String = Clipboard.GetDataObject().GetData(System.Windows.Forms.DataFormats.Text).ToString()

        If Not stString Is Nothing Then
            Me.SelectedText = GetPermitedString(stString, Me.PermitChars)
        End If
    End Sub

  #End Region

  #Region " [S] HasPermitChars メソッド "

    ' 許可された文字かどうかを示す値を返す
    Private Shared Function HasPermitChars(ByVal chTarget As Char, ByVal chPermits As Char()) As Boolean
        For Each ch As Char In chPermits
            If chTarget = ch Then
                Return True
            End If
        Next ch
    End Function

  #End Region

  #Region " [S] GetPermitedString メソッド "

    ' 許可された文字だけを連結して返す
    Private Shared Function GetPermitedString(ByVal stTarget As String, ByVal chPermits As Char()) As String
        Dim stReturn As String = String.Empty

        For Each chTarget As Char In stTarget
            If HasPermitChars(chTarget, chPermits) Then
                stReturn &= chTarget
            End If
        Next chTarget

        Return stReturn
    End Function

  #End Region

End Class

あとは、この MyTextBox をフォームに追加して以下のように、許可する文字を設定すれば良いです。

VB.NET 全般
    ' 0 ~ 5 の入力を許可する
    Me.MyTextBox1.PermitChars = New Char() {"0"c, "1"c, "2"c, "3"c, "4"c, "5"c};

関連するリファレンス

準備中です。

スポンサーリンク