[C#] TextBox限制輸入長度 (中文字算2碼)

[C#] TextBox限制輸入長度 (中文字算2碼)

操作環境: ,

 

如果是要計算中文字長度算2碼
可以參考我這篇文章: [C#] 讓中文字長度等於2

 

TextBox本身有一個MaxLength的屬性可以限制輸入長度
但他計算長度的方式是不論中文字還英文字都算1碼
如果要配合SQL Server的Varchar欄位做長度限制
那遇到中文字的部份就很容易出錯了
因為中文字存到Varchar欄位佔用的長度算2碼

 

既然TextBox.MaxLength屬性沒辦法達到我們的需求
那就自己重寫一個TextBox控制項
並增加MaxByteLength的屬性

public partial class uTextBox : TextBox
{
    uint _maxByteLength = 0;
    public uint MaxByteLength //用來限制輸入長度, 中文字長度以2碼來計算
    {
        get { return _maxByteLength; }
        set { _maxByteLength = value; }
    }
}

 

然後在OnKeyPress事件中
判斷輸入的長度是不是超過MaxByteLength設定的長度
這邊要注意的是若user有選取文字的話
因為選取的文字是即將被取代掉的

所以要先把那些文字的長度減去
才不會發生key不進去的囧境

protected override void OnKeyPress(KeyPressEventArgs e)
{
    base.OnKeyPress(e);
    
    if (ReadOnly) return; //唯讀不處理
    if (_maxByteLength == 0) return; //沒設定MaxByteLength不處理
    if (char.IsControl(e.KeyChar)) return; //Backspace, Enter...等控制鍵不處理
    
    int textByteLength = Encoding.GetEncoding(950).GetByteCount(Text + e.KeyChar.ToString()); //取得原本字串和新字串相加後的Byte長度
    int selectTextByteLength = Encoding.GetEncoding(950).GetByteCount(SelectedText); //取得選取字串的Byte長度, 選取字串將會被取代
    if (textByteLength - selectTextByteLength > _maxByteLength) e.Handled = true; //相減後長度若大於設定值, 則不送出該字元
}

註: Encoding.GetEncoding(950) == Encoding.GetEncoding("big5")

 

還有一點要注意的是
如果user是用複製貼上的方式
因為貼上的資料不會經過OnKeyPress事件檢核
所以我們必須把複製的資料攔截下來後
再拆解成一個字元一個字元的傳遞給OnKeyPress去檢核

int WM_PASTEDATA = 0x0302; //貼上資料的訊息
 
protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_PASTEDATA) //如果收到貼上資料的訊息, 包括Ctrl+V, Shift+Ins和滑鼠右鍵選單中的貼上
        SendCharFromClipboard(); //就把剪貼簿中的字串一個字元一個字元的拆開, 再傳給自己
    else
        base.WndProc(ref m);
}
 
int WM_CHAR = 0x0102;
 
private void SendCharFromClipboard()
{
    foreach (char c in Clipboard.GetText())
    {
        Message msg = new Message();
        msg.HWnd = Handle;
        msg.Msg = WM_CHAR;
        msg.WParam = (IntPtr)c;
        msg.LParam = IntPtr.Zero;
        base.WndProc(ref msg);
    }
}

 

這樣就大功告成了
來看看畫面

image

 

 

[範例Code下載]

 

 

OnKeyPress事件中檢核方式稍微變通一下
就可以做出限制只能輸入英文/數字
或是數字轉大寫...等等的功能了

 


by sam319