[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);
}
}
這樣就大功告成了
來看看畫面
[範例Code下載]
OnKeyPress事件中檢核方式稍微變通一下
就可以做出限制只能輸入英文/數字
或是數字轉大寫...等等的功能了
by sam319