(C#)为 TextBox 控件增加一个限制最大字节数的属性

一直以来都知道,在 sql server 中,varchar类型是按字节计算的。例如 varchar(50)  可以存储50个英文字符,但只能存储25个中文字符(一个中文字符2个字节)。改为 nvarchar 可以解决这个问题,但在写sql语句的时候必须加上N标识,否则会产生乱码。

但最近用 C# 做数据库项目,才知道问题很严重。本来输入的合法性就应该在界面上做好限制,例如对于varchar(50) 的字段,能在界面上控制用户不能输入超过50个单字节字符,是最好不过的了。然后发现 textbox 的 MaxLength 计算的只是 Unicode 长度。

对于 Unicode ,我这里就不做描述了。设置 MaxLength  是不能很好的保证输入的合法性。因此我决定为 textbox 增加一个限制最大字节数的属性:MaxByteLength 。

建立新组件

我们先新建一个组件 TextBoxEx,继承于 TextBox ,增加一个 MaxByteLength  属性

public partial class TextBoxEx : TextBox
    
{
        
public TextBoxEx()
        
{
            InitializeComponent();
        }


        
属性

然后重写 WndProc ,实现输入和粘贴的时候对字节长度进行判断。(已修正输入“.”号没有判断的问题)

        protected override void WndProc(ref Message m)
        {
            
//如果该属性没有设置,则允许输入
            if (m_MaxByteLength == 0)
            {
                
base.WndProc(ref m);
                
return;
            }

            
switch (m.Msg)
            {
                
case WM_CHAR:
                    
int i = (int)m.WParam;
                    
bool isBack = (i == (int)Keys.Back);
                    
bool isCtr = (i == 24|| (i == 22|| (i == 26|| (i == 3);

                    
if (isBack || isCtr)
                    {
                        
//控制键不作处理
                    }
                    
else
                    {
                        
char c = (char)i;
                        
if (CheckByteLengthFlow(c.ToString()))
                        {
                            
break;
                        }
                    }
                    
base.WndProc(ref m);
                    
break;
                
case WM_PASTE:
                    IDataObject iData 
= Clipboard.GetDataObject();//取剪贴板对象
                    if (iData.GetDataPresent(DataFormats.Text)) //判断是否是Text
                    {
                        
string text = (string)iData.GetData(DataFormats.Text);//取数据
                        if (CheckByteLengthFlow(text))
                        {
                            m.Result 
= (IntPtr)0;//不可以粘贴
                            break;
                        }
                    }
                    
base.WndProc(ref m);
                    
break;
                
default:
                    
base.WndProc(ref m);
                    
break;
            }
        }

        
/// <summary>
        
/// 判断即将输入的文本长度是否溢出
        
/// </summary>
        
/// <param name="text">文本</param>
        
/// <returns>是否溢出</returns>
        private bool CheckByteLengthFlow(string text)
        {
            
int len = GetByteLength(text);    //输入的字符的长度
            int tlen = GetByteLength(this.Text);  //文本框原有文本的长度
            int slen = GetByteLength(this.SelectedText);    //文本框选中文本的长度
            return (m_MaxByteLength < (tlen - slen + len));
        }

        
/// <summary>
        
/// 计算文本字节长度,区分多字节字符
        
/// </summary>
        
/// <param name="text">文本</param>
        
/// <returns>文本字节长度</returns>
        private int GetByteLength(string text)
        {
            
return System.Text.Encoding.Default.GetBytes(text).Length;
        }


另外,增加一个 RealText 属性,该属性返回具有合法长度的文本, 不会截断多字节字符
public string RealText
        
{
            
get
            
{
                
if (m_MaxByteLength == 0)
                
{
                    
return this.Text;
                }


                
if (m_MaxByteLength >= GetByteLength(this.Text))
                
{
                    
return this.Text;
                }


                
string text = this.Text;

                
if (string.IsNullOrEmpty(text))
                
{
                    
return text;
                }


                
char[] c = text.ToCharArray();
                StringBuilder sb 
= new StringBuilder();
                
int count = 0;

                
for (int i = 0; i < c.Length; i++)
                
{
                    count 
+= GetByteLength(c[i].ToString());
                    
if (m_MaxByteLength >= count)
                    
{
                        sb.Append(c[i]);
                    }

                }


                
return sb.ToString();
            }

        }

至此,可以通过设置 MaxByteLength  来限制最大字节数了。

源代码下载:/Files/lemony/TextBoxExTest_OLD.rar
posted on 2007-04-10 18:03  柠檬隐士  阅读(16141)  评论(27编辑  收藏  举报