如何实现C 如何实现CT每一层扫描
创始人
2024-06-06 13:21:27
0

C#旨在设计成为一种「简单、现代、通用」,以及面向对象的程序设计语言。其中c# textbox数字输入需要注意的一些情况容易被忽略,针对这一情况,笔者将在这篇文章中分享自己的一些经验。

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

在定制的c# textbox数字控件中,如果只允许输入数字,需要考虑如下三种情况:

正常按键输入的字符,包括西文、中文字符等

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

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

1、重写键盘事件OnKeyPress()

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

  1. protected override void OnKeyPress(KeyPressEventArgs e)  // 屏蔽非数字键  
  2. {  
  3.     base.OnKeyPress(e);  
  4.     if (this.ReadOnly)  // 只读, 不处理  
  5.     {  
  6.         return;  
  7.     }  
  8.             if ((int)e.KeyChar <= 32)  // 特殊键(含空格), 不处理  
  9.     {  
  10.         return;  
  11.     }  
  12.         if (!char.IsDigit(e.KeyChar))  // 非数字键, 放弃该输入  
  13.     {  
  14.         e.Handled = true;  
  15.         return;  
  16.     }  

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

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

  1. protected override bool ProcessCmdKey(ref Message msg, Keys keyData)  
  2.   {  
  3.     if (keyData == (Keys)Shortcut.CtrlV)  // 快捷键 Ctrl+V 粘贴操作  
  4.     {  
  5.         this.ClearSelection();  
  6.         string text = Clipboard.GetText();  
  7.         for (int k = 0; k < text.Length; k++) // can not use SendKeys.  
  8.         {  
  9.             // 通过消息模拟键盘输入, SendKeys.Send()静态方法不行  
  10.             SendCharKey(text[k]);  
  11.         }  
  12.         return true;      
  13. }  
  14.     return base.ProcessCmdKey(ref msg, keyData);  
  1. private void SendCharKey(char c)  // 通过消息模拟键盘录入  
  2. {  
  3.     Message msg = new Message();  
  4.     msg.HWnd = this.Handle;  
  5.     msg.Msg = WM_CHAR;  // 输入键盘字符消息 0x0102  
  6.     msg.WParam = (IntPtr)c;  
  7.     msg.LParam = IntPtr.Zero;  
  8.     base.WndProc(ref msg);  


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

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

  1. public class CustomTextBox: TextBox  
  2. {  
  3.     // 创建无内容菜单对象, 等价屏蔽该控件的上下文菜单  
  4.     this.ContextMenu = new ConTextMenu();  
  5.   } 

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

  1. protected override void WndProc(ref Message m)  // 捕获Mouse的Paste消息  
  2. {  
  3.     if (m.Msg == WM_PASTE)  // 选择上下文菜单的"粘贴"操作    {  
  4.         this.ClearSelection();  
  5.         SendKeys.Send(Clipboard.GetText());  // 模拟键盘输入  
  6.     }  
  7.     else 
  8.     {  
  9.         base.WndProc(ref m);  
  10.     }  

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

还必须分析前面代码中的两个函数:
ClearSelection()用以清除当前的选择文本,即清除this.SelectedText
DeleteText()则删除当前字符
需要指出其中的技巧,就是转换Delete键操作为BackSpace操作。此外,函数DeleteText()还需要确定当前的this.SelectionStart值。具体代码如下:

  1. private void ClearSelection() // 清除当前TextBox的选择  
  2. {  
  3.     if (this.SelectionLength == 0)  
  4.     {  
  5.         return;  
  6.     }  
  7.     int selLength = this.SelectedText.Length;    this.SelectionStart += this.SelectedText.Length;  // 光标在选择之后  
  8.     this.SelectionLength = 0;  
  9.     for (int k = 1; k <= selLength; k++)  
  10.     {  
  11.         this.DeleteText(Keys.Back);  
  12.     }  
  1. private void DeleteText(Keys key) // 删除字符并计算SelectionStart值  
  2. {  
  3.     int selStart = this.SelectionStart;  
  4.     if (key == Keys.Delete)  // 转换Delete操作为BackSpace操作  
  5.     {   
  6.        selStart += 1;  
  7.         if (selStart > base.Text.Length)  
  8.         {   
  9.            return;  
  10.         }  
  11.     }  
  12.     if (selStart == 0 || selStart >base.Text.Length)  // 不需要删除  
  13.     {  
  14.         return;  
  15.     }  
  16.     if (selStart == 1 && base.Text.Length == 1)   
  17.    {  
  18.         base.Text = "";  
  19.         base.SelectionStart = 0;  
  20.     }  
  21.     else  // selStart > 0  
  22.     {  
  23.         base.Text = base.Text.Substring(0, selStart - 1) +  
  24.             base.Text.Substring(selStart, base.Text.Length - selStart);  
  25.         base.SelectionStart = selStart - 1;  
  26.     }  

5、结语

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

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

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

上述内容是从笔者的开源数值型数据编辑控件TNumEditBox中修改删减而来的,该控件考虑的情况比只允许数字输入要复杂得多,感兴趣者可以参考并指正。需要指出,TNumEditBox的核心思路来自免费的Delphi控件PBNumEdit和开源的C#控件BANumEdit。作为回报,笔者也将TNumEditBox开源并发布到CodeProject。

本文来自:CSDN博客   作者:huihui

【编辑推荐】

  1. 编程语言排行榜:C语言当选08年年度编程语言
  2. C++标准委员会确定将concepts特性从C++0x中移除
  3. C#interface定义及使用浅析
  4. C#3.0新特性的介绍(自动属性)
  5. C#HTTP文件传输的实现浅析

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...