もなかアイスの試食品

「とりあえずやってみたい」そんな気持ちが先走りすぎて挫折が多い私のメモ書きみたいなものです.

【C#】整数・数値入力用のTextBoxを作ってみた

TextBoxに整数・数値だけ入力し、それ以外は入力させない時がよくあります。

色んなサイトを探して見つかっても、小数点が複数個入力できたり、これだ!って思える処理が中々見つからない。(実は探すのが面倒くさくなってきたり・・・)

という訳で、以下のサイトを参考にしつつ、作ってみました。

・参考にしたサイト

TextBoxに数字しか入力できないようにする: .NET Tips: C#, VB.NETTextBoxに数字しか入力できないようにする: .NET Tips: C#, VB.NET

入力制限をしたいと言っても、符号の有無・小数点の有無があるので、列挙で区別するようにします。

namespace NumberTextBox
{
    /// <summary>NumberTextBox のタイプ</summary>
    enum NumberTextBoxType
    {
        /// <summary>符号なし整数</summary>
        UnsignedInteger,

        /// <summary>符号あり整数</summary>
        SignedInteger,

        /// <summary>符号なし数値(小数あり)</summary>
        UnsignedDecimal,

        /// <summary>符号あり数値(小数あり)</summary>
        SignedDecimal,
    }
}

TextBoxなので、FrameWorkのTextBoxを継承して、新しいクラスを作成しました。

ちなみに、使用しているFrameWorkは2.0なので、プロパティ用のメンバ変数を用意しています。

namespace NumberTextBox
{
    /// <summary>数値入力を行う Windows テキスト ボックス コントロールを表します。</summary>
    class NumberTextBox
        : TextBox
    {
        #region コンストラクタ ----------------------------------------------------------------------------------------------------------------------

        /// <summary>クラスの新しいインスタンスを初期化します。</summary>
        public NumberTextBox()
            : base()
        {
            this.MaxLength = 15;
            this.NumberType = NumberTextBoxType.UnsignedInteger;
        }

        #endregion コンストラクタ -------------------------------------------------------------------------------------------------------------------

        #region Public ------------------------------------------------------------------------------------------------------------------------------

        /// <summary>書式フォーマットを指定します。</summary>
        public string Format
        {
            get
            {
                return this.m_format;
            }
            set
            {
                this.m_format = value;
            }
        }

        /// <summary>格納する数値のタイプを指定します。</summary>
        public NumberTextBoxType NumberType
        {
            get
            {
                return this.m_numberType;
            }
            set
            {
                this.m_numberType = value;
            }
        }

        #endregion Public ---------------------------------------------------------------------------------------------------------------------------

        #region Private -----------------------------------------------------------------------------------------------------------------------------

        /// <summary>プロパティ格納用 書式フォーマット</summary>
        private string m_format;

        /// <summary>プロパティ格納用 格納する数値のタイプ</summary>
        private NumberTextBoxType m_numberType;

        /// <summary>System.Windows.Forms.Control.KeyPress イベントを発生させます。</summary>
        /// <param name="e">イベント データを格納している System.Windows.Forms.KeyPressEventArgs。</param>
        protected override void OnKeyPress( KeyPressEventArgs e )
        {
            base.OnKeyPress( e );

            char pressKey = e.KeyChar;
            bool inFormat = false;

            if ( pressKey != '\b' ) // バックスペース以外は入力OKかどうかチェック
            {
                switch ( this.NumberType )
                {
                    case NumberTextBoxType.SignedDecimal:
                        inFormat = Regex.IsMatch( this.Text + pressKey, @"^[+-]?[0-9]*\.?[0-9]*$" );
                        break;
                    case NumberTextBoxType.SignedInteger:
                        inFormat = Regex.IsMatch( this.Text + pressKey, @"^[+-]?[0-9]*$" );
                        break;
                    case NumberTextBoxType.UnsignedDecimal:
                        inFormat = Regex.IsMatch( this.Text + pressKey, @"^[0-9]*\.?[0-9]*$" );
                        break;
                    case NumberTextBoxType.UnsignedInteger:
                        inFormat = Regex.IsMatch( this.Text + pressKey, @"^[0-9]*$" );
                        break;
                    default:
                        throw new NotSupportedException();
                }
                if ( inFormat == false )
                {
                    e.Handled = /*InputIgnore*/true;
                }
            }
        }

        /// <summary>System.Windows.Forms.Control.Validating イベントを発生させます。</summary>
        /// <param name="e">イベント データを格納している System.ComponentModel.CancelEventArgs。</param>
        /// <remarks>
        /// <para>Format または Text プロパティが Null または空文字のときは検証を行わない。</para>
        /// </remarks>
        protected override void OnValidating( System.ComponentModel.CancelEventArgs e )
        {
            base.OnValidating( e );

            if ( String.IsNullOrEmpty( this.Format ) || String.IsNullOrEmpty( this.Text ) )
            {
                return;
            }

            try
            {
                switch ( this.NumberType )
                {
                    case NumberTextBoxType.SignedDecimal:
                    case NumberTextBoxType.UnsignedDecimal:
                        {
                            double inputValue = Double.Parse( this.Text );
                            this.Text = String.Format( "{0:" + this.Format + "}", inputValue );
                        }
                        break;
                    case NumberTextBoxType.SignedInteger:
                    case NumberTextBoxType.UnsignedInteger:
                        {
                            int inputValue = Int32.Parse( this.Text );
                            this.Text = String.Format( "{0:" + this.Format + "}", inputValue );
                        }
                        break;
                }
            }
            catch( FormatException ex )
            {
                MessageBox.Show( ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error );
                this.Focus();
                this.SelectAll();
            }
        }

        #endregion Private --------------------------------------------------------------------------------------------------------------------------
    }
}

作った「NumberTextBox」クラスを実際に使ってみました。

符号・小数ありの数値を例にします。正の数値なら「+」を負の数値なら「-」を先頭に表示し、小数点3桁まで表示するようにFormatを設定

namespace sample
{
    public partial class Form1
        : Form
    {
        /// <summary>コンストラクタ。メンバの初期化を行います。</summary>
        public Form1()
        {
            this.InitializeComponent();

            this.符号あり数値.NumberType = NumberTextBox.NumberTextBoxType.SignedDecimal;
            this.符号あり数値.Format = "+0.000;-0.000";
        }
    }
}

適当に数値を入力

入力時

フォーカスが移った時に、Formatプロパティで設定された書式に変換されます。

入力後


NumberTextBoxのOnKeyPressメソッドのせいで、テキストを全選択しても、バックスペースしか受け付けないのはちょっと痛いかも・・・

改善の余地ありですな。