当前位置:文档之家› C#TextBox中只允许输入数字的解决方法

C#TextBox中只允许输入数字的解决方法

C#TextBox中只允许输入数字的解决方法

最近看到一些关于TextBox中限制只允许输入数字的博文,这类问题常常用事后处理模式:录入字符结束后在控件离开(如Exit事件)或确认时进行判断。本文探讨控件录入操作的事前处理模式:做录入操作时屏蔽非数字字符。下面,结合笔者前段时间修改完善的开源数值文框TNumEditBox控件,介绍一个基于定制TextBox控件的解决方法。

在定制的TextBox控件中,如果只允许输入数字,需要考虑如下三种情况:正常按键输入的字符,包括西文、中文字符等

通过键盘快捷键方式贴入的文本,即Ctrl+V操作

通过上下文关联菜单的Mouse操作贴入的文本,即”粘贴“操作

在探讨的同类文章中,多数只考虑了第1种情况,忽略得了第2、3种常见的操作。本文探讨的处理方法核心思路是重写事件OnKeyPress()和两个方法ProcessCmdKey()与WndProc(),并把Ctrl+V、关联菜单的Paste操作统一到键盘录入操作中,从而在OnKeyPress()屏蔽掉非数字键。

1、重写键盘事件OnKeyPress()

键盘输入的字符可以通过重写TextBox控件的OnKeyPress()事件处理,见如下代码:

protectedoverridevoidOnKeyPress(KeyPressEventArgse)//屏蔽非数字键{base.OnKeyPress(e);if(this.ReadOnly)//只读,不处理{return;}if((int)e.KeyChar<=32)//特殊键(含空格),不处理{return;}if(!char.IsDigit(e.KeyChar))//非数字键,放弃该输入{e.Handled=true;return;}}

2、重写命令键处理方法ProcessCmdKey()

可以在ProcessCmdKey()中捕获快捷键Ctrl+V操作。首先要清除当前的选择文本,然后读取剪切板ClipBoard中的内容,最后通过模拟键盘输入的方式”输入“ClipBoard的内容。需要指出,在ProcessCmdKey()方法中不能使用静态方法SendKeys.Send(),但可以通过控件的WndProc()方法发送字符消息以达到模拟键盘录入的目的。见如下代码:

protectedoverrideboolProcessCmdKey(refMessagemsg,KeyskeyData)//捕获Ctrl+V{if(keyData==(Keys)Shortcut.CtrlV)//快捷键Ctrl+V粘贴操作{this.ClearSelection();stringtext=Clipboard.GetText();for(intk=0;k

SendCharKey(text[k]);}returntrue;}returnbase.ProcessCmdKey(refmsg,key Data);}privatevoidSendCharKey(charc)//通过消息模拟键盘录入{Messagemsg=newMessage();msg.HWnd=this.Handle;msg.Msg=WM_CHAR;//输入键盘字符消息

0x0102msg.WParam=(IntPtr)c;msg.LParam=IntPtr.Zero;base.WndProc(refmsg );}

3、重写消息处理方法WndProc()

可以在定制TextBox控件中创建无内容的上下文菜单对象,从而屏蔽该菜单,方法是在定制控件的构造函数中增加如下代码:

publicclassCustomTextBox:TextBox{//创建无内容菜单对象,等价屏蔽该控件的上下文菜单this.ContextMenu=newConTextMenu();}由于上下文菜单的Paste操作对应Windows的WM_PASTE消息,于是可以在控件的WndProc()方法中捕获该消息,然后获得剪切板ClipBoard中的内容,最后通过SendKeys.Send()方法模拟键盘录入操作。需要注意,这里不能调用前面ProcessCmdKey()中模拟键盘输入函数SendCharKey()。见如下代码:

protectedoverridevoidWndProc(refMessagem)//捕获Mouse的Paste消息{if(m.Msg==WM_PASTE)//选择上下文菜单的"粘贴"操作{this.ClearSelection();SendKeys.Send(Clipboard.GetText());//模拟键盘输入}else{base.WndProc(refm);}}

4、消除选择ClearSelection()、删除字符DeleteText()

还必须分析前面代码中的两个函数:

ClearSelection()用以清除当前的选择文本,即清除this.SelectedText DeleteText()则删除当前字符

需要指出其中的技巧,就是转换Delete键操作为BackSpace操作。此外,函数DeleteText()还需要确定当前的this.SelectionStart值。具体代码如下:privatevoidClearSelection()//清除当前TextBox的选择{if(this.SelectionLength==0){return;}intselLength=this.SelectedText.L ength;this.SelectionStart+=this.SelectedText.Length;//光标在选择之后this.SelectionLength=0;for(intk=1;k<=selLength;k++){this.DeleteText(K eys.Back);}}privatevoidDeleteText(Keyskey)//删除字符并计算SelectionStart值{intselStart=this.SelectionStart;if(key==Keys.Delete)//转换Delete操作为BackSpace操作{selStart+=1;if(selStart>base.Text.Length){return;}}if(selStart==0||s

elStart>base.Text.Length)//不需要删除{return;}if(selStart==1&&base.Text.Length==1){base.Text="";base.Selec tionStart=0;}else//selStart>0{base.Text=base.Text.Substring(0,selStar t-1)+base.Text.Substring(selStart,base.Text.Length-selStart);base.Sel ectionStart=selStart-1;}}

5、结语

本文探讨的是TextBox控件输入的事前处理模式,即在输入字符的同时屏蔽非数字键。在实际应用中一般采取事后处理模式,即在TextBox控件的Exit、Validate等事件中进行输入后处理――离开该控时进行验证。但事后处理模式有如下不足:

与数据源绑定时输入非数字字符可能抛出异常,需要考虑异常捕获

需要判断数据并给出错误提示等处理

这里探讨的是屏蔽非数字键输入,显然可以推广到屏蔽其它特殊键如Tab 和指定字母等。

相关主题
文本预览
相关文档 最新文档