1. 前言
最近在写定GPS定位时,经纬度是用的double类型,并且经纬度的要求是小数点后最少6位,多了能达到17位,又遇到了常用的TextBox控件只能输入数字、小数的功能,因为有一年多没有写程序,现在再来写这些感觉已经忘记的差不多了,这次干脆把功能进行扩展,写到这里以作记录,并分享与大家。
2. 功能
(1)TextBox文本框只能输入0-9和小数点以及BackSpace删除键。
(2)文本框小数点只能有一位。
(3)文本框内第一位如果直接输入小数点,会自动在其前面补0,形成“0.”开头的格式。
(4)因为TexbBox控件增加了我们自己“只能输入数字小数点和删除键功能”的KeyPress事件,会导致TextBox控件的Ctrl+C和Ctrl+V功能失效,只能用鼠标来执行复制粘贴,所以此次通过TextBox控件的KeyDown事件进行了修复,文本框的复制和粘贴功能又恢复正常。
(5)对文本框Ctrl+V粘贴剪切板的内容进行了处理,把剪切板内非数字和小数点部分过滤掉了。也就是说你复制了含有字母、汉字、空格、特殊符号等非数字字符,粘贴到文本框时会把它们去掉,只留下含有数字的部分。
(6)其余对文本框选中内容的操作,我们处理的跟Windows系统操作方法一样。
3. 程序代码
/// <summary>/// 只能输入数字、小数点、删除键,并且第1位输入小数点,自动在前面补0,形成"0."格式/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void NumPointKeypress(object sender, KeyPressEventArgs e){//除了数字、小数点、删除键的其他键,程序不输出if (!((e.KeyChar >= '0' && e.KeyChar <= '9') || e.KeyChar == '.' || e.KeyChar == (char)Keys.Back)){e.Handled = true;}//按键是小数点if (e.KeyChar == '.'){//获取当前文本框对象TextBox textbox = sender as TextBox;//文本框的文本已经有小数点if (textbox.Text.IndexOf('.') >= 0){//文本框选定的文本包括小数点,再次输入小数点时就把选定的内容删除并换成小数点if (textbox.SelectedText.Contains(".")){//选定带小数点文本的起始位置(索引)int Index = textbox.SelectionStart;//从第一位开始选定带小数点的文本,输入小数点时直接在前面补0,形成"0."开头的文本,光标置于小数点后if (Index == 0){textbox.Text = textbox.Text.Remove(Index, textbox.SelectionLength).Insert(Index, "0.");textbox.SelectionStart = Index + 2;}else//选定小数点的文本是起始位置在第一位之后,再次输入小数点直接将选定内容替换成小数点,光标置于小数点后{textbox.Text = textbox.Text.Remove(Index, textbox.SelectionLength).Insert(Index, ".");textbox.SelectionStart = Index + 1;}textbox.SelectionLength = 0;// 确保没有文本被选中}e.Handled = true;}else if (string.IsNullOrEmpty(textbox.Text))//文本框不含小数点,并且文本框内容为空{//方法1:直接将小数点写入文本起始位置,格式"0.",按键不输出//textbox.Text = "0.";//textbox.SelectionStart = 2; //光标在文本框中第三个字符处(位置索引为2)//textbox.SelectionLength = 0; // 确保没有文本被选中//e.Handled = true;//方法2:不写入小数点,在文本起始位置写入0,按键输出小数点textbox.Text = "0";textbox.SelectionStart = 1; //光标在文本框中第二个字符处(位置索引为2)textbox.SelectionLength = 0; // 确保没有文本被选中}else if (!string.IsNullOrEmpty(textbox.Text))//文本框不含小数点,并且文本框已经有内容{/* * 光标位于文本框最前面,用一条语句解决下面两种情况:* 第一种情况,有选定内容,直接删除后插入"0",按键再输出小数点,* 第二种情况,没有选定内容,下面语句text.Text.Remove(0,0)相当于没有替换,* 也是直接在文本最前面插入了"0",按键再输出小数点,*/if (textbox.SelectionStart == 0){textbox.Text = textbox.Text.Remove(0, textbox.SelectionLength).Insert(0, "0");textbox.SelectionStart = 1; //光标置于小数点后textbox.SelectionLength = 0; // 确保没有文本被选中}//光标不在文本框最前面,在其他任意位置,文本内容选中与不选中,都会按系统自己的方式插入小数点。}}}/// <summary>/// 允许文本框复制、粘贴/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void NumPointKeydown(object sender, KeyEventArgs e){TextBox textbox = sender as TextBox;if (e.KeyData == (Keys.Control | Keys.C)){Clipboard.SetDataObject(textbox.SelectedText);}if (e.KeyData == (Keys.Control | Keys.V)){//文本框中的文本未选中情况下,把剪切板中的插入光标处if (textbox.SelectionLength == 0){//将原文本框中的文本与插入剪切板中的字符进行过滤(如果剪切板中有非数字字符,多余一位的小数点都将去除)textbox.Text = FilterString(textbox.Text.Insert(textbox.SelectionStart, Clipboard.GetText()));}else//文本在选中情况下,删除掉选中的文本,再把剪切板中的插入此处{int Index = textbox.SelectionStart;textbox.Text = textbox.Text.Remove(Index, textbox.SelectionLength).Insert(Index, Clipboard.GetText());//将原文本框中的文本与插入剪切板中的字符进行过滤(如果剪切板中有非数字字符,多余一位的小数点都将去除)textbox.Text = FilterString(textbox.Text);}//粘贴完成后,光标置于文本最后textbox.SelectionStart = textbox.Text.Length;}}/// <summary>/// 把剪切板中的英文、汉字、特殊字符等非数字字符过滤掉/// 如果存在多个小数点,只留第一位小数点/// </summary>/// <param name="clipboardText">剪切板组合的内容</param>/// <returns>返回整数或浮点数字符串</returns>private string FilterString(string clipboardText){// 匹配浮点数或整数string pattern = @"[+-]?(\d+(\.\d*)?|\.\d+)";System.Text.RegularExpressions.MatchCollection matches = System.Text.RegularExpressions.Regex.Matches(clipboardText, pattern);string Filterstring = string.Empty;foreach (System.Text.RegularExpressions.Match match in matches){Filterstring += match.Value;}//如果存在多个小数点,留下第一个小数点,其他的都删除int PointCounts = Filterstring.Where(p => p == '.').Count();if (PointCounts >= 2){for (int i = 0; i < PointCounts - 1; i++){Filterstring = Filterstring.Remove(Filterstring.LastIndexOf('.'), 1);}}//过滤后不存在数字部分则返回字符0if (string.IsNullOrEmpty(Filterstring))return "0";else{//过滤后第一位是小数点,则在其前面加0if (Filterstring.FirstOrDefault() == '.')Filterstring = "0" + Filterstring;return Filterstring;}}
注意:如果在Ctrl+V粘贴时不需要对剪切板中的内容进行过滤,而是直接要使用剪切板的内容,可以在NumPointKeydown()事件中使用 textbox.Text = Clipboard.GetText(),就不需要再调用FilterString()字符过滤函数了。
4. 调用
可以在窗口文件的构造函数中直接调用,也可以在窗口载入事件Load()中调用,以窗口构造函数为例。
public Form1(){InitializeComponent();//绑定事件以下事件://1、文本框只能输入数字、小数点、删除键的事件textBox1.KeyPress += NumPointKeypress;textBox2.KeyPress += NumPointKeypress;//2、文本框允许复制、粘贴textBox1.KeyDown += NumPointKeydown;textBox2.KeyDown += NumPointKeydown;}