DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

DOBON.NET

TextBoxに数字しか入力できないようにする

テキストボックス(ここではTextBox1)に数字以外の文字が入力できないようにする方法を幾つか紹介します。

注意:ここで紹介した方法だけでは、数字以外の文字列が入力されることを完全に防げることはできません。入力された文字列が本当に数字だけか確かめ、そうでなければ拒否するためには、必ずTextBoxのValidatingイベントをしようしてください。文字列が数字に変換できるか調べる方法に関しては、こちらをご覧ください。(コメントによるご指摘により、追記しました。)

KeyPressイベントによる方法

テキストボックスのKeyPressイベントで数字以外のキー入力をキャンセルするには、次のようなコードを書きます。

[VB.NET]
Private Sub TextBox1_KeyPress(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.KeyPressEventArgs) _
        Handles TextBox1.KeyPress
    If e.KeyChar < "0"c Or e.KeyChar > "9"c Then
        e.Handled = True
    End If
End Sub
[C#]
 private void TextBox1_KeyPress(object sender,
    System.Windows.Forms.KeyPressEventArgs e)
{
    if (e.KeyChar < '0' || e.KeyChar > '9')
    {
        e.Handled = true;
    }
}

補足:「e.KeyChar < '0' || e.KeyChar > '9'」(VB.NETでは「e.KeyChar < "0"c Or e.KeyChar > "9"c」)の条件式は、「!Char.IsDigit(e.KeyChar)」(VB.NETでは「Not Char.IsDigit(e.KeyChar)」)とすることもできます。

補足:.NET Framework 2.0からは、KeyDownイベントハンドラでKeyEventArgs.SuppressKeyPressプロパティをTrueにすることによっても、キー入力を無効にすることができます。KeyDownイベントハンドラでSuppressKeyPressプロパティをTrueにすると、KeyPressイベントは発生しなくなります。

さらにバックスペース文字も許可するには、次のようにします。許可する文字を増やしたい時は、同様にしてIf文の条件式に許可する文字を追加してください。

[VB.NET]
Private Sub TextBox1_KeyPress(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.KeyPressEventArgs) _
        Handles TextBox1.KeyPress
    If (e.KeyChar < "0"c Or e.KeyChar > "9"c) And e.KeyChar <> vbBack Then
        e.Handled = True
    End If
End Sub
[C#]
 private void TextBox1_KeyPress(object sender,
    System.Windows.Forms.KeyPressEventArgs e)
{
    if ((e.KeyChar < '0' || e.KeyChar > '9') && e.KeyChar != '\b')
    {
        e.Handled = true;
    }
}

補足:入力された文字が制御文字か調べるには、「Char.IsControl(e.KeyChar)」とすることもできます。

IMEのオン、クリップボードからの貼り付けを防ぐ

しかしこれだけではIMEがオンになっている時は数字以外の文字が入力されてしまいます。これを出来ないようにするにはテキストボックスのImeModeプロパティをDisableにしておきます。

またクリップボードにコピーされた文字列を貼り付けることによっても数字以外を入力できてしまいます。クリップボードからのペーストを防ぐ方法は、「TextBoxにペースト(貼り付け)できないようにする」で説明しています。ここで紹介しているWM_PASTEメッセージを無視する方法を少しいじって、数字のみで構成された文字列がクリップボードにあるときは貼り付けできないようにしたコードを以下に示します。(ここでは文字列が数字であるかごく簡単にしか調べていません。詳しく調べる方法は、こちらを参考にしてください。)

[VB.NET]
''' <summary>
''' マウスやキーボードによる数字以外のペーストを無効にしたTextBox
''' </summary>
Public Class MyTextBox
    Inherits TextBox
    Private WM_PASTE As Integer = &H302

    Protected Overrides Sub WndProc(ByRef m As Message)
        If m.Msg = WM_PASTE Then
            Dim iData As IDataObject = Clipboard.GetDataObject()
            '文字列がクリップボードにあるか
            If iData.GetDataPresent(DataFormats.Text) Then
                Dim clipStr As String = _
                    CStr(iData.GetData(DataFormats.Text))
                'クリップボードの文字列が数字か調べる
                If Not System.Text.RegularExpressions.Regex.IsMatch( _
                    clipStr, "^\d+$") Then
                    Return
                End If
            End If
        End If
        MyBase.WndProc(m)
    End Sub
End Class
[C#]
//using System.Windows.Forms;
//がソースファイルの一番上に書かれているものとする

/// <summary>
/// マウスやキーボードによる数字以外のペーストを無効にしたTextBox
/// </summary>
public class MyTextBox : TextBox
{
    const int WM_PASTE = 0x302;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_PASTE)
        {
            IDataObject iData = Clipboard.GetDataObject();
            //文字列がクリップボードにあるか
            if (iData.GetDataPresent(DataFormats.Text))
            {
                string clipStr = (string) iData.GetData(DataFormats.Text);
                //クリップボードの文字列が数字か調べる
                if (!System.Text.RegularExpressions.Regex.IsMatch(
                    clipStr,
                    @"^\d+$"))
                    return;
            }
        }

        base.WndProc(ref m);
    }
}

NumericUpDownコントロールを使う方法

テキストボックスを使わずにNumericUpDownコントロールを使うという手も考えられます。しかし、この場合もIMEが効かないようにしないと、文字が入力できてしまいますし、コピー&ペーストもできてしまいます。数字以外の文字が入力された場合、Valueプロパティで値を取得すると、それ以前に入力されていた数字が返され、NumericUpDownコントロールにもその数字が表示されます。

CreateParamsをオーバーライドする方法

もう1つ方法を紹介しましょう。これは、ニュースグループで紹介されていた方法です。CreateParams.StyleにES_NUMBERを追加しています。この方法でもやはりコピー&ペーストで文字列以外の文字を入力できてしまいます。

[VB.NET]
''' <summary>
''' 数字しかキー入力できないTextBox
''' </summary>
Public Class NumericTextBox
    Inherits TextBox
    Private ES_NUMBER As Integer = &H2000

    Protected Overrides ReadOnly Property CreateParams() As CreateParams
        Get
            Dim parms As CreateParams = MyBase.CreateParams
            parms.Style = parms.Style Or ES_NUMBER
            Return parms
        End Get
    End Property
End Class
[C#]
//using System.Windows.Forms;
//がソースファイルの一番上に書かれているものとする

/// <summary>
/// 数字しかキー入力できないTextBox
/// </summary>
public class NumericTextBox : TextBox
{
    const int ES_NUMBER = 0x2000;

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams parms = base.CreateParams;
            parms.Style |= ES_NUMBER;
            return parms;
        }
    }
}

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。