【KPI】英数字以外が入力不可のテキストボックスを作成する。【VB.Net】【C#】

以前お仕事で必要になった際に調べて作ったもの。
テキストボックスに、DBのキー項目となるコードを入力する際、記号などが入力出来てしまうのを弾きたかった。
以下、VB.Netの新しいコード用テキストボックスクラス。

``` VB.Net:VB.Net
Imports System.Text.RegularExpressions

Public Class CommonClass

    ''' <summary>
    ''' 正規表現フォーマット
    ''' </summary>
    Public Enum RegexFormat

        LimitLess = 0
        Num
        AlphaUp
        AlphaLow
        NumAlphaLowUp

    End Enum

    ''' <summary>
    ''' コード用テキストボックス
    ''' </summary>
    Public Class CodeTextBox
        Inherits TextBox

        ''' <summary>
        ''' 入力フォーマット
        ''' </summary>
        Private _Format As RegexFormat = RegexFormat.LimitLess

        ''' <summary>
        ''' （保持用）テキスト開始位置
        ''' </summary>
        Private selectionStartCustom As Integer = 0

        ''' <summary>
        ''' 入力フォーマット
        ''' </summary>
        Public Property Format() As RegexFormat
            Get
                Return _Format
            End Get
            Set(ByVal value As RegexFormat)
                _Format = value
            End Set
        End Property

        ''' <summary>
        ''' 正規表現フォーマット文字列取得処理
        ''' </summary>
        ''' <param name="regexFormat">正規表現フォーマット</param>
        ''' <param name="notTarget">true:指定した対象以外を正規表現で取得する</param>
        ''' <returns>正規表現フォーマット文字列</returns>
        Private Function GetRegexFormat(ByVal regexFormat As RegexFormat, ByVal notTarget As Boolean) As String

            Dim notFormatWord As String = String.Empty

            GetRegexFormat = String.Empty

            If notTarget Then

                notFormatWord = "^"

            End If

            Select Case (regexFormat)
                Case regexFormat.Num
                    GetRegexFormat = "[" + notFormatWord + "0-9]"
                    Exit Select
                Case regexFormat.AlphaUp
                    GetRegexFormat = "[" + notFormatWord + "A-Z]"
                    Exit Select
                Case regexFormat.AlphaLow
                    GetRegexFormat = "[" + notFormatWord + "a-z]"
                    Exit Select
                Case regexFormat.NumAlphaLowUp
                    GetRegexFormat = "[" + notFormatWord + "0-9a-zA-Z]"
                    Exit Select
            End Select

        End Function

        ''' <summary>
        ''' IMEモード（半角のみ入力）
        ''' </summary>
        Protected Overloads Property ImeMode() As ImeMode
            Get
                Return ImeMode.Disable
            End Get
            Set(ByVal value As ImeMode)

            End Set
        End Property

        Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
            ' テキスト開始位置をこの時点で取得
            selectionStartCustom = Me.SelectionStart
            MyBase.OnKeyPress(e)
        End Sub

        Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)

            If Not _Format.Equals(RegexFormat.LimitLess) Then

                Dim reg As Regex = New Regex(GetRegexFormat(_Format, True))
                Dim result As String = reg.Replace(Me.Text, String.Empty)

                If Not result.Equals(Me.Text) Then

                    Me.Text = result
                    Me.SelectionStart = selectionStartCustom

                End If

            End If

            MyBase.OnTextChanged(e)
        End Sub

    End Class

End Class
```
また、C#版も記述しておく。

``` C#:C#
    class CommonClass
    {
        /// <summary>
        /// 正規表現フォーマット
        /// </summary>
        public enum RegexFormat
        {
            LimitLess = 0,
            Num,
            AlphaUp,
            AlphaLow,
            NumAlphaLowUp
        }

        /// <summary>
        /// 正規表現フォーマット文字列取得処理
        /// </summary>
        /// <param name="regexFormat">正規表現フォーマット</param>
        /// <param name="notTarget">true:指定した対象以外を正規表現で取得する</param>
        /// <returns>正規表現フォーマット文字列</returns>
        private static string GetRegexFormat(RegexFormat regexFormat, bool notTarget)
        {
            string format = string.Empty;
            string notFormatWord = string.Empty;

            if (notTarget)
            {
                notFormatWord = "^";
            }

            switch (regexFormat)
            {
                case RegexFormat.Num:
                    format = "[" + notFormatWord + "0-9]";
                    break;
                case RegexFormat.AlphaUp:
                    format = "[" + notFormatWord + "A-Z]";
                    break;
                case RegexFormat.AlphaLow:
                    format = "[" + notFormatWord + "a-z]";
                    break;
                case RegexFormat.NumAlphaLowUp:
                    format = "[" + notFormatWord + "0-9a-zA-Z]";
                    break;
            }

            return format;
        }

        /// <summary>
        /// コード用テキストボックス
        /// </summary>
        public class CodeTextBox : TextBox
        {
            /// <summary>
            /// フォーマット（正規表現の選択）
            /// </summary>
            [AmbientValue(RegexFormat.LimitLess)]
            [Localizable(true)]
            public RegexFormat Format { get; set; }

            /// <summary>
            /// （保持用）テキスト開始位置
            /// </summary>
            private int selectionStart = 0;

            //[AmbientValue(ImeMode.Disable)]
            //// プロパティウィンドウ非表示
            //[Browsable(false)]
            //// インテリセンス非表示
            //[EditorBrowsable(EditorBrowsableState.Never)]
            //public new ImeMode ImeMode { get { return base.ImeMode; } set { base.ImeMode = ImeMode.Disable; } }

            protected override void OnKeyPress(KeyPressEventArgs e)
            {
                // テキスト開始位置をこの時点で取得
                selectionStart = base.SelectionStart;
                base.OnKeyPress(e);
            }

            protected override void OnTextChanged(EventArgs e)
            {
                if (!Format.Equals(RegexFormat.LimitLess))
                {
                    Regex reg = new Regex(GetRegexFormat(Format, true));
                    string result = reg.Replace(this.Text, string.Empty);

                    if (!result.Equals(this.Text))
                    {
                        base.Text = result;
                        base.SelectionStart = selectionStart;
                    }
                }
                base.OnTextChanged(e);
            }
        }
    }
```

・今後の課題
　①ImeModeプロパティは制御不可にしたい。
　②処理中の描画がされるため、入力不可の文字を入力した瞬間のみ描画されることがあるので、この間は描画したくない。