표준 TextBox에서 파생 된 간단한 독립 실행 형 Winforms 사용자 지정 컨트롤은 System.Int32 입력 만 허용합니다 (System.Int64 등의 다른 유형에 쉽게 적용 할 수 있음). 복사 / 붙여 넣기 작업과 음수를 지원합니다.
public class Int32TextBox : TextBox
{
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
NumberFormatInfo fi = CultureInfo.CurrentCulture.NumberFormat;
string c = e.KeyChar.ToString();
if (char.IsDigit(c, 0))
return;
if ((SelectionStart == 0) && (c.Equals(fi.NegativeSign)))
return;
// copy/paste
if ((((int)e.KeyChar == 22) || ((int)e.KeyChar == 3))
&& ((ModifierKeys & Keys.Control) == Keys.Control))
return;
if (e.KeyChar == '\b')
return;
e.Handled = true;
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
const int WM_PASTE = 0x0302;
if (m.Msg == WM_PASTE)
{
string text = Clipboard.GetText();
if (string.IsNullOrEmpty(text))
return;
if ((text.IndexOf('+') >= 0) && (SelectionStart != 0))
return;
int i;
if (!int.TryParse(text, out i)) // change this for other integer types
return;
if ((i < 0) && (SelectionStart != 0))
return;
}
base.WndProc(ref m);
}
2017 업데이트 : 첫 번째 답변에는 몇 가지 문제가 있습니다.
- 주어진 유형의 정수보다 긴 것을 입력 할 수 있습니다 (예 : 2147483648이 Int32.MaxValue보다 큼).
- 더 일반적으로, 입력 된 결과 에 대한 실제 검증은 없습니다 .
- int32 만 처리하므로 각 유형 (Int64 등)에 대해 특정 TextBox 파생 컨트롤을 작성해야합니다.
그래서 복사 / 붙여 넣기, + 및-기호 등을 계속 지원하는 더 일반적인 다른 버전을 생각해 냈습니다.
public class ValidatingTextBox : TextBox
{
private string _validText;
private int _selectionStart;
private int _selectionEnd;
private bool _dontProcessMessages;
public event EventHandler<TextValidatingEventArgs> TextValidating;
protected virtual void OnTextValidating(object sender, TextValidatingEventArgs e) => TextValidating?.Invoke(sender, e);
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (_dontProcessMessages)
return;
const int WM_KEYDOWN = 0x100;
const int WM_ENTERIDLE = 0x121;
const int VK_DELETE = 0x2e;
bool delete = m.Msg == WM_KEYDOWN && (int)m.WParam == VK_DELETE;
if ((m.Msg == WM_KEYDOWN && !delete) || m.Msg == WM_ENTERIDLE)
{
DontProcessMessage(() =>
{
_validText = Text;
_selectionStart = SelectionStart;
_selectionEnd = SelectionLength;
});
}
const int WM_CHAR = 0x102;
const int WM_PASTE = 0x302;
if (m.Msg == WM_CHAR || m.Msg == WM_PASTE || delete)
{
string newText = null;
DontProcessMessage(() =>
{
newText = Text;
});
var e = new TextValidatingEventArgs(newText);
OnTextValidating(this, e);
if (e.Cancel)
{
DontProcessMessage(() =>
{
Text = _validText;
SelectionStart = _selectionStart;
SelectionLength = _selectionEnd;
});
}
}
}
private void DontProcessMessage(Action action)
{
_dontProcessMessages = true;
try
{
action();
}
finally
{
_dontProcessMessages = false;
}
}
}
public class TextValidatingEventArgs : CancelEventArgs
{
public TextValidatingEventArgs(string newText) => NewText = newText;
public string NewText { get; }
}
Int32의 경우 다음과 같이 파생시킬 수 있습니다.
public class Int32TextBox : ValidatingTextBox
{
protected override void OnTextValidating(object sender, TextValidatingEventArgs e)
{
e.Cancel = !int.TryParse(e.NewText, out int i);
}
}
또는 파생없이 다음과 같이 새로운 TextValidating 이벤트를 사용하십시오.
var vtb = new ValidatingTextBox();
...
vtb.TextValidating += (sender, e) => e.Cancel = !int.TryParse(e.NewText, out int i);
그러나 좋은 점은 모든 문자열 및 모든 유효성 검사 루틴에서 작동한다는 것입니다.