一直以来都知道,在 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 为允许无限长度。
        /// </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  来限制最大字节数了。

源代码下载:/Files/lemony/TextBoxExTest_OLD.rar

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

  1. c#winform连接扫码枪,并将光标定位在textBox控件上

    c#winform连接扫码枪,并将光标定位在textBox控件上 前期准备: 扫码枪为斑马DS2278型号,先创建一个.txt文件,将扫码枪连接到电脑上,会自动下载驱动,这时扫码,码值会出现记事本上, ...

  2. ASP.Net基本控件之TextBox控件

    前言 Asp.net服务器控件是微软为了方便开发者开发而推出的一系列控件,他们都以类似 <asp:*ID="btnOK" runat="server" - ...

  3. html asp:textbox,ASP .NET - TextBox 控件

    添加脚本 当表单被提交时,TextBox 控件的内容和设置可通过服务器脚本进行修改.可通过点击一个按钮或当用户更改 TextBox 控件中的值对表单进行提交. 在下面的例子中,我们在一个 .aspx ...

  4. 露雨资源库三(第一个.net2.0软件)-为控件增加自动完成功能

    前面我写过"露雨资源库"的第一篇和第二篇,分别介绍了界面设计和设计思路. 链接如下: 露雨资源库(第一个.net2.0软件)一 http://luyu.cnblogs.com/ar ...

  5. C#WinForm判断界面上多个TextBox控件的值是否为空

    说明:当WinForm界面上面有多个控件需要判断是否为空,如果用if(){}else,难免有些繁琐.在参考了其他博主的资料以后,我这里也做了一些整理,以TextBox控件示例,如下. VS打开创建一个 ...

  6. VB.NET学习笔记:自定义控件之扩展TEXTBOX控件——水印文字提示效果

    测试环境:windows 7和Microsoft Visual Studio 2017 看到一些优秀软件里的TEXTBOX文本框都有水印文字提示应该输入什么样的信息,获取光标后提示文字消失,光标离开后 ...

  7. 设置TextBox控件的高度文档翻译

    原文来自: https://www.codeproject.com/Articles/29140/Set-TextBox-Height 翻译:Jeffrey Chou 设置TextBox控件的高度(S ...

  8. C#仿QQ皮肤-TextBox 控件实现

    C#仿QQ皮肤-实现原理系列文章导航                                                               http://www.cnblogs. ...

  9. WPF控件之自定义TextBox控件

    首先我们要知道用户控件与自定义用户控件的确保 用户控件 1将多个现有的控件组合成一个可重用的"组". 2不能使用样式和模板. 3继承自UserControl类. 自定义控件 1在现 ...

最新文章

  1. ubuntu 安装OpenBLAS
  2. linux一切皆文件之tty字符设备(深入理解sshd创建pty的过程) (五)
  3. linux内核杂记(2)-内核的同步与并发
  4. 基于mindspore的口罩检测训练与在线推理
  5. android 写字体投影,android-给字体设置投影
  6. Python学习笔记-2017.8.08
  7. php 调用日历控制,基于ThinkPHP实现的日历功能实例详解
  8. 我的MyGeneration
  9. java js base64_java与js转base64编码格式
  10. 小程序服务商申请入口_商业版微信收款小程序商家申请开通流程指导
  11. 稀土储量由80%变成了35%?这是何等的。。。
  12. webmax函数高级教程整理集2
  13. 设定个人发展目标和计划
  14. php论坛整合,phpcms+ucenter+discuz论坛整合教程
  15. python数据驱动创建账号_20190705-Python数据驱动之DDT
  16. vim 配置文件 ,高亮+自动缩进+行号+折叠+优化
  17. 最新系统MacOs13 Ventura(M1/M2芯片) + Parallels Desktop 18(PD18史上最强虚拟机)永久使用攻略
  18. java开发微信公众号:微信公众号对接
  19. 综测仪 IQ简介和IQview使用方法
  20. Freebsd7 Xorg7.3 KDE3.5 桌面系统安装及美化

热门文章

  1. Flask-Login Flask-Security 登录与权限控制
  2. cocoa pods Installation
  3. extjs插件开发上传下载文件简单案例
  4. HDU 2176(Nim博弈)
  5. 大三时候实现的,关于大整数(超过long范围)加减乘除操作的头文件,并包含了实现RSA加解密的函数...
  6. 给一名准90后程序员的指导——学好IT?无用论?
  7. 使用Grunt构建任务管理脚本(转)
  8. ubuntu下面安装Keil uvision4与入门实例
  9. 彻底卸载nodejs和npm然后使用nvm
  10. pad_sequences序列填充(转载)