数字または一部の文字しか入力できないようにする
スポンサーリンク
テキストボックスで数字または一部の文字しか入力できないようにするには、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};
関連するリファレンス
準備中です。