你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 编程语言
2.14 Visual C#中实现约束文本编辑框
 

 

一、       引言

.NET提供了功能强大的Windows窗体设计器,让开发人员快速的建立所想要的用户界面,在开发过程中经常会使用到文本编辑控件TextBox,让用户进行输入。但在实际应用中,可能需要对用户的输入进行限制,例如:一个要求输入日期的文本框,在不加限制的情况下,用户输入的月份或天数可能超出实际的范围,或者输入了其它非数字的字符,这样就容易导致程序处理出现错误。虽然TextBox控件提供了validatedvalidating事件来验证文本框的内容,但是这种验证方式只有在用户输入完成后才能触发验证事件,来提示用户输入错误,操作性不友好。如果事先给文本框设置一个输入格式,在用户输入每个字符的过程中就对内容进行验证,不符合格式的字符拒绝输入,这样就可以保证输入内容的正确。本文以输入日期和时间为例介绍实现带约束功能的文本框。

二、       TextBox控件的KeyPress事件

1. KeyPress事件

要实现对输入的每个字符进行检查,必须获取用户键入的每一个字符,获取键盘的输入可以使用TextBox控件的KeyPress事件,该事件在控件有焦点的情况下按键时发生,该事件传递KeyPressEventArgs类型的参数,KeyPressEventArgs类有两个关键参数:

bool Handled

char KeyChar

Handled用来指示是否处理过KeyPress事件,处理过为true,否则为false。如果只是想处理键盘事件而不想控件接收键盘字符,则应将Handled设为true

KeyChar用来获取或设置与按下的键对应的字符。

2. 使用事件

要在应用程序中使用事件,必须提供一个事件处理程序,该处理程序执行程序逻辑以响应事件并向事件源注册事件处理程序。例如定义一个处理KeyPress事件的程序:

         Void MyDateTimeEdit_KeyPress(object sender, KeyPressEventArgs e)
         {
         }

然后将事件处理程序添加到TextBoxKeyPress事件。

         KeyPress += new KeyPressEventHandler(MyEdit_KeyPress);

三、       实现原理

本文以输入固定格式的日期和时间字符串为例,输入的格式必须为“2007-11-24 12:12:12”,输入的月份数值不能超过12,天数不能超过31,输入小时的数值不能超过23,分钟和秒的值不能超过59。掩码字符串:掩码为输入字符提供基本的格式,包括字符的取值、长度。本文中掩码设为“0000-00-00 00:00:00。它代表的意义为:掩码中为0的字符是允许用户更改的,且必须为数字,其它字符固定不可更改,用户输入的字符串长度不能大于掩码的长度。

参照字符串:参照字符串为输入的字符提供位置参考,格式为“____-__-__ __:__:__”,当输入的字符处于参照字符串的‘_’位置时允许用户继续输入,否则系统直接输出该字符,不需用户键入。

输入字符串:用来记录用户输入的合法字符,格式与掩码相同,但是随用户的输入而更改。

实现步骤:

1)初始化掩码字符串、参照字符串和输入字符串,输入字符串初始值等于掩码字符串。

2)等待用户输入。

3)触发KeyPress事件,获得用户在文本框中输入的位置x和字符c

4)在掩码中找到第x个字符m,如果字符m0,则判断字符c是否为数字,如果不是数字,则返回到(2)重新执行,否则用字符c替换输入字符串的第x个字符。

5)将输入位置x向后移动一个位置,获得新位置yx1,然后判断参照字符串中第y个字符p是否为“_”,如果是执行步骤(2),否则将字符p作为参数触发KeyPress事件,执行步骤(3)。

6)循环执行上述过程,直到用户输入字符串的长度等于掩码长度。

四、       实现代码

1.在Visual C#开发环境中创建一个基于Windows的应用程序,工程名为“EditMask”。

2.添加一个新类,命名为“MyDateTimeEdit”,然后将基类改为“System.Windows.Forms.TextBox”,这样新类可以具有TextBox的所有功能,新类的定义如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Media;
 
namespace EditMask
{
         class MyDateTimeEdit : System.Windows.Forms.TextBox
         {
         }
}

3.  MyDateTimeEdit类添加KeyPress事件:

         void MyEdit_KeyPress(object sender, KeyPressEventArgs e)

然后添加KeyPress事件:

         KeyPress += new KeyPressEventHandler(MyEdit_KeyPress);

为了使控件只显示输入字符串,不自动接受字符处理,将Handle变量设为true

    MyDateTimeEdit类的实现代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Media;
namespace EditMask
{
    //该类从TextBox继承
    class MyDateTimeEdit : System.Windows.Forms.TextBox
    {
        public bool m_bMaskKeyInProgress;         
        public bool m_bUseMask;                  //是否启用约束编辑功能
        public bool m_bIsDatetime;                //按照日期时间格式约束
        public String m_strMask;                  //掩码字符串
        public String m_strLiteral;                 //参照字符串
        public String m_strMaskLiteral;
        public String m_strHours;                //小时的参考变量
        public String m_strMins;                 //分钟的参考变量
        public String m_strSeconds;              //秒的参考变量
        public StringBuilder m_str;              //输入字符串
        public MyDateTimeEdit()
        {
            KeyPress += new KeyPressEventHandler(MyEdit_KeyPress);//添加KeyPress事件
            //初始化变量
            m_bMaskKeyInProgress = false;
            m_bUseMask = true;
            m_bIsDatetime = true;
            m_strHours = "23";
            m_strMins = "59";
            m_strSeconds = "59";
            m_strMask = "0000-00-00 00:00:00";     //初始化掩码字符串格式
            m_strLiteral = "____-__-__ __:__:__";    //初始化参照字符串格式
            m_str = new StringBuilder("0000-00-00 00:00:00", 19);//初始化输入字符串
            m_strMaskLiteral = m_str.ToString();
            Text = m_str.ToString();                 //显示输入字符串
            this.Select(0, 0);
        }
        //KeyPress事件处理方法
        private void MyEdit_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;       //Handled设为true,不处理键入的字符
            char nChar = e.KeyChar;         //获取键入的字符
            char c;
            if (!m_bMaskKeyInProgress)
            {
                if (!CheckChar(nChar))     //判断输入的字符是否符合格式
                    return;
            }
 
            if (m_bUseMask)
            {
                if (!Char.IsControl(nChar))//判断输入字符是否控制键
                {
                    //获取当前选择文本的起始和结束位置
                    int startPos, endPos;
                    startPos = SelectionStart;
                    endPos = SelectionStart + SelectionLength;
                    Select(startPos, endPos + 1);
                    m_str[endPos] = nChar; //更新输入字符串
                }
                else if (nChar == (char)Keys.Back)//处理BackSpace
                {
                    int startPos, endPos;
                    startPos = SelectionStart;
                    endPos = SelectionStart + SelectionLength;
 
                    //如果按下回退键,则显示掩码字符串的相应字符
                    if ((startPos == endPos) && (startPos >= 1) && (startPos <= m_str.Length))
                    {
                        
                        if (m_strMaskLiteral != "")
                        {
                            c = m_strMaskLiteral[startPos - 1];
                            SelectionStart = startPos - 1;
                            SendChar(c);
                            SelectionStart -= 1;
                        }
                    }
                    else
                        MessageBeep();//播放警告音
                    return;
                }
            }
            int selectionStart = SelectionStart;
            Text = m_str.ToString();//显示输入字符串
            SelectionStart = selectionStart + 1;//光标后移一位
            Select(SelectionStart, 0);
            if (!m_bMaskKeyInProgress && m_bUseMask && m_strLiteral != "")
            {
                int startPos, endPos;
                startPos = SelectionStart;
                endPos = SelectionStart + SelectionLength;
                // 判断输入位置是否在掩码位,否则直接输出该字符
                if (endPos < m_strLiteral.Length)
                {
                    c = m_strLiteral[endPos];
                    if (c != '_')
                        SendChar(c);
                }
            }
        }
        //检测输入字符是否符合要求
        private bool CheckChar(char nChar)
        {
            char c;
            if (!m_bUseMask) return true;
            // 是否控制键
            if (Char.IsControl(nChar)) return true;
            // 取消选择
            int startPos, endPos;
            startPos = SelectionStart;
            endPos = SelectionStart + SelectionLength;
            Select(startPos, 0);
            // 输入位置大于掩码长度,播放警告音
            if (endPos >= m_strMask.Length)
            {
                MessageBeep();
                return false;
            }
         
            c = '_';
            if (m_strLiteral != "")
                c = m_strLiteral[endPos];
 
            if (c != '_')
            {
                SendChar(c);
                startPos = SelectionStart;
                endPos = SelectionStart + SelectionLength;
            }
        
            c = m_strMask[endPos];
            bool doit = true;
            switch (c)
            {
                case '0'//只接受数字键输入
                    {
                        doit = true;
                        if (Char.IsDigit(nChar))//判断输入字符是否为数字
                        {
                            if (m_bIsDatetime)
                            {
                                //如果输入月份值,则判断是否在正确范围内,输入范围不能大于12
                                if (endPos == 5)
                                {
                                    if (nChar > '1')
                                        doit = false;
                                }
                                if (endPos == 6)
                                {
                                    if (m_str[5] == '1')
                                    {
                                        if (nChar > '2')
                                            doit = false;
                                    }
                                }
                                //如果是输入天数,范围不能大于31
                                if (endPos == 8)
                                {
                                    if (nChar > '3')
                                        doit = false;
                                }
                                if (endPos == 9)
                                {
                                    if (m_str[8] == '3')
                                    {
                                        if (nChar > '1')
                                            doit = false;
                                    }
                                }
                                //输入的小时范围不能超过23
                                if (endPos == 11)
                                {
                                    if (nChar > m_strHours[0])
                                        doit = false;
                                }
                                if (endPos == 12)
                                {
                                    if (m_str[11] == m_strHours[0])
                                    {
                                        if (nChar > m_strHours[1])
                                            doit = false;
                                    }
                                }
                                //分钟的范围不能超过59
                                if (endPos == 14)
                                {
                                    if (nChar > m_strMins[0])
                                        doit = false;
                                }
                                if (endPos == 15)
                                {
                                    if (m_str[14] == m_strMins[0])
                                    {
                                        if (nChar > m_strMins[1])
                                            doit = false;
                                    }
                                }
                                //秒的范围不能超过59
                                if (endPos == 17)
                                {
                                    if (nChar > m_strSeconds[0])
                                        doit = false;
                                }
                                if (endPos == 18)
                                {
                                    if (m_str[17] == m_strSeconds[0])
                                    {
                                        if (nChar > m_strSeconds[1])
                                            doit = false;
                                    }
                                }
                            }
                            return doit;
                        }
                        break;
                    }
            }
            //不正确输入,警告音提示
            MessageBeep();
            return false;
        }
        //以字符c触发KeyPress事件
        private void SendChar(char c)
        {
            m_bMaskKeyInProgress = true;
            KeyPressEventArgs e = new KeyPressEventArgs(c);
            MyEdit_KeyPress(this, e);
            m_bMaskKeyInProgress = false;
        }
        //播放警告音
        private void MessageBeep()
        {
            SystemSounds.Beep.Play();
        }
    }
}

4.添加一个“TextBox”控件,命名为“textBox1,在Form1类中打开“InitializeComponent()”函数,将控件类型修改为“MyDateTimeEdit”,并初始化文本,修改结果见代码粗体部分:

private void InitializeComponent()
{
    this.textBox1 = new EditMask.MyDateTimeEdit();
    this.SuspendLayout();
    this.textBox1.Location = new System.Drawing.Point(66, 68);
    this.textBox1.Name = "textBox1";
    this.textBox1.Size = new System.Drawing.Size(155, 21);
    this.textBox1.TabIndex = 0;
    this.textBox1.Text = "0000-00-00 00:00:00";
    
    }

5.程序运行结果见图1



                       1  带约束功能的文本框

本文代码在Visual Studio 2005下编译通过。

 

 

  推荐精品文章

·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089