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

スポンサーリンク

テキストボックスで数字または一部の文字しか入力できないようにするには、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 の配列が許可された文字になり、ここに登録されていない文字の入力はできなくなります。

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

サンプルコード

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

C# 全般
// 以下の名前空間をインポートする
using System.Windows.Forms;

public class MyTextBox : System.Windows.Forms.TextBox {

  #region コンストラクタ

    public MyTextBox() {
        this.PermitChars = new char[] {};
    }

  #endregion

  #region PermitChars プロパティ

    private char[] _PermitChars;

    public char[] PermitChars {
        get {
            return this._PermitChars;
        }

        set {
            this._PermitChars = value;
        }
    }

  #endregion

  #region WndProc メソッド (override)

    protected override void WndProc(ref System.Windows.Forms.Message m) {
        const int WM_CHAR  = 0x0102;
        const int WM_PASTE = 0x0302;

        switch (m.Msg) {
            case WM_CHAR:
                if ((this.PermitChars != null) && (this.PermitChars.Length > 0)) {
                    KeyPressEventArgs eKeyPress = new KeyPressEventArgs((char)(m.WParam.ToInt32()));
                    this.OnChar(eKeyPress);

                    if (eKeyPress.Handled) {
                        return;
                    }
                }
                break;
            case WM_PASTE:
                if ((this.PermitChars != null) && (this.PermitChars.Length > 0)) {
                    this.OnPaste(new System.EventArgs());
                    return;
                }
                break;
        }

        base.WndProc(ref m);
    }

  #endregion

  #region OnChar メソッド (virtual)

    protected virtual void OnChar(KeyPressEventArgs e) {
        if (char.IsControl(e.KeyChar)) {
            return;
        }

        if (! HasPermitChars(e.KeyChar, this.PermitChars)) {
            e.Handled = true;
        }
    }

  #endregion

  #region OnPaste メソッド (virtual)

    protected virtual void OnPaste(System.EventArgs e) {
        string stString = Clipboard.GetDataObject().GetData(System.Windows.Forms.DataFormats.Text).ToString();

        if (stString != null) {
            this.SelectedText = GetPermitedString(stString, this.PermitChars);
        }
    }

  #endregion

  #region [S] HasPermitChars メソッド

    private static bool HasPermitChars(char chTarget, char[] chPermits) {
        foreach (char ch in chPermits) {
            if (chTarget == ch) {
                return true;
            }
        }

        return false;
    }

  #endregion

  #region [S] GetPermitedString メソッド

    private static string GetPermitedString(string stTarget, char[] chPermits) {
        string stReturn = string.Empty;

        foreach (char chTarget in stTarget) {
            if (HasPermitChars(chTarget, chPermits)) {
                stReturn += chTarget;
            }
        }

        return stReturn;
    }

  #endregion

}

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

C# 全般
    // 0 ~ 5 の入力を許可する
    this.myTextBox1.PermitChars = new char[] {'0', '1', '2', '3', '4', '5'};

関連するリファレンス

準備中です。

スポンサーリンク