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

本文介绍了一种在C#中为TextBox控件添加字节数限制的方法,确保输入内容符合数据库VARCHAR字段的长度要求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一直以来都知道,在 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  属性

None.gif public  partial  class  TextBoxEx : TextBox
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
public TextBoxEx()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            InitializeComponent();
ExpandedSubBlockEnd.gif        }

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
属性#region 属性
InBlock.gif
InBlock.gif        
private int m_MaxByteLength = 0;
InBlock.gif        [Description(
"获取或设置用户可在文本框控件中键入或粘贴的最大字节数。0 为允许无限长度。")]
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 获取或设置用户可在文本框控件中键入或粘贴的最大字节数。0 为允许无限长度。
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public int MaxByteLength
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn m_MaxByteLength; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ m_MaxByteLength = value; }
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif}

然后重写 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 属性,该属性返回具有合法长度的文本, 不会截断多字节字符
None.gif public   string  RealText
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (m_MaxByteLength == 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
return this.Text;
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
if (m_MaxByteLength >= GetByteLength(this.Text))
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
return this.Text;
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
string text = this.Text;
InBlock.gif
InBlock.gif                
if (string.IsNullOrEmpty(text))
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
return text;
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
char[] c = text.ToCharArray();
InBlock.gif                StringBuilder sb 
= new StringBuilder();
InBlock.gif                
int count = 0;
InBlock.gif
InBlock.gif                
for (int i = 0; i < c.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    count 
+= GetByteLength(c[i].ToString());
InBlock.gif                    
if (m_MaxByteLength >= count)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        sb.Append(c[i]);
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
return sb.ToString();
ExpandedSubBlockEnd.gif            }

ExpandedBlockEnd.gif        }

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

源代码下载: /Files/lemony/TextBoxExTest_OLD.rar
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值