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();
}
#region 属性
private int m_MaxByteLength = 0;
[Description("获取或设置⽤户可在⽂本框控件中键⼊或粘贴的最⼤字节数。0 为允许⽆限长度。")]
///<summary>
/// 获取或设置⽤户可在⽂本框控件中键⼊或粘贴的最⼤字节数。0 为允许⽆限长度。
textbox控件边框设置///</summary>
public int MaxByteLength
{
get { return m_MaxByteLength; }
set { m_MaxByteLength = value; }
}
}
然后重写 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 来限制最⼤字节数了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论