入力制限付きテキストボックス
Visual C#の標準のTextBoxに対して、入力制限をかけられる拡張テキストボックスを作成してみました。入力制限は、正規表現で表します。
ソース
InputLimitTextBox.cs
using System; using System.ComponentModel; using System.Windows.Forms; namespace ClassLibrary { /// <summary> /// 入力制限ありテキストボックス /// </summary> public class InputLimitTextBox : System.Windows.Forms.TextBox { private string _InputLimit = string.Empty; private System.Text.RegularExpressions.Regex _InputLimitRegex = null; [Description("許可する入力文字列を表す正規表現を設定します。例:英数字 \\w*、浮動小数点 \\d{0,5}(\\.\\d{0,2})?")] public virtual string InputLimit { get { return _InputLimit; } set { _InputLimit = value; _InputLimitRegex = new System.Text.RegularExpressions.Regex("^" + _InputLimit + "$"); Text = string.Empty; } } /// <summary> /// テキスト変更中イベント /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public delegate void TextChangingEventHandler(object sender, TextChangingEventArgs e); [Description("Text プロパティの値がコントロールで変更される直前に発生します。")] public event TextChangingEventHandler TextChanging; #region protectedメソッド protected virtual void OnTextChanging(TextChangingEventArgs e) { // 入力チェック if (_InputLimitRegex.Match(e.NewText).Success != true) { e.Cancel = true; } // ユーザ定義のイベントを呼ぶ if (TextChanging != null) { TextChanging(this, e); } } protected override void WndProc(ref System.Windows.Forms.Message m) { const int WM_KEYDOWN = 0x100; const int WM_CHAR = 0x102; const int WM_PASTE = 0x302; switch (m.Msg) { case WM_CHAR: // 文字が入力された場合 { TextChangingEventArgs e = new TextChangingEventArgs( this.CreateNewText(Convert.ToString((char)(m.WParam.ToInt32())))); this.OnTextChanging(e); if (e.Cancel == true) { // 入力された文字をキャンセルする return; } } break; case WM_KEYDOWN: if (m.WParam.ToInt32() == (int)Keys.Delete) { // Deleteキーが押された場合 TextChangingEventArgs e = new TextChangingEventArgs( this.CreateNewText(string.Empty, true)); this.OnTextChanging(e); if (e.Cancel == true) { // Deleteキーをキャンセルする m.Result = new IntPtr(1); // true return; } } break; case WM_PASTE: // 貼り付けされた場合 // クリップボードから入力内容を取得する string clipText = (string)Clipboard.GetDataObject().GetData(DataFormats.Text); if (clipText != null) { TextChangingEventArgs e = new TextChangingEventArgs(this.CreateNewText(clipText)); this.OnTextChanging(e); if (e.Cancel == true) { // 入力された内容をキャンセルする return; } } break; } // 親クラスのWndProcを呼ばないと、イベント内容がなかったことになる。 base.WndProc(ref m); } #endregion #region privateメソッド /// <summary> /// 擬似的に変更後のテキストを作成する /// </summary> /// <param name="inputText"></param> /// <returns></returns> private string CreateNewText(string inputText) { return this.CreateNewText(inputText, false); } /// <summary> /// 擬似的に変更後のテキストを作成する /// </summary> /// <param name="inputText"></param> /// <param name="deleteKey"></param> /// <returns></returns> private string CreateNewText(string inputText, bool deleteKey) { // 画面表示されているテキストを初期設定し、 // 範囲選択されている文字列を削除する。 string newText = this.Text; newText = newText.Remove(this.SelectionStart, this.SelectionLength); // Delete キーを入力 if (deleteKey) { if (this.SelectionLength == 0 && this.SelectionStart < this.TextLength) { newText = newText.Remove(this.SelectionStart, 1); } return newText; } // テキストボックスが複数行対応してなければ、 // 引数のテキストから改行コードを削除する。 if (this.Multiline == false) { int crIndex = inputText.IndexOf("\r"); if (crIndex > 0) { inputText = inputText.Remove(crIndex); } int lrIndex = inputText.IndexOf("\n"); if (lrIndex > 0) { inputText = inputText.Remove(lrIndex); } } // ここまでで、引数のテキストがブランクとなっていれば、処理終了する。 if (inputText == string.Empty) { return newText; } // BackSpace キーを入力 if (Convert.ToInt32(inputText[0]) == (int)Keys.Back) { if (this.SelectionLength == 0 && this.SelectionStart > 0) { newText = newText.Remove(this.SelectionStart - 1, 1); } } else { newText = newText.Insert(this.SelectionStart, inputText); } return newText; } #endregion } }
TextChangingEventArgs.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ClassLibrary { /// <summary> /// テキスト変更中に発生するイベントクラス。 /// </summary> public class TextChangingEventArgs : System.ComponentModel.CancelEventArgs { /// <summary> /// 変更後のテキスト /// </summary> private string _NewText; public TextChangingEventArgs() { this._NewText = string.Empty; } public TextChangingEventArgs(string text) { this._NewText = text; } /// <summary> /// 変更後のテキスト /// </summary> public string NewText { get { return this._NewText; } } } }
NumericLimitTextBox.cs
※InputLimitTextBoxを数値入力制限に特化したもの
using System; using System.ComponentModel; using System.Windows.Forms; namespace ClassLibrary { /// <summary> /// 数値入力制限テキストボックス /// </summary> public class NumericLimitTextBox : InputLimitTextBox { private int _IntLength = 10; private int _ScaleLength = 2; [DefaultValue(10)] [Description("整数部の桁数を設定します。")] public int IntLength { get { return _IntLength; } set { _IntLength = value; SetInputLimit(); } } [DefaultValue(2)] [Description("小数部の桁数を設定します。")] public int ScaleLength { get { return _ScaleLength; } set { _ScaleLength = value; SetInputLimit(); } } public override string InputLimit { get { return base.InputLimit; } } #region protectedメソッド protected void SetInputLimit() { base.InputLimit = "\\d{0," + _IntLength + "}(\\.\\d{0," + _ScaleLength + "})?"; } #endregion } }
環境
- OS:Windows Vista
- Visual C#:2008 Express Edition
参考サイト
- [VB, C#] テキストボックスにテキスト変更中イベントを作成する
- http://youryella.wankuma.com/Library/Default.aspx
- 「参考」というか、ほぼそのまま流用となってしまいました。