經常某些輸入的文本要求只能是數字等,比如qq登陸框上的qq帳號,如果按鍵不是數字,則沒有反應。原理當然是很簡單的,只需要在相應訊息到來時阻止控制項去處理訊息即可。
這種例子很多,當然可以override keypress事件。也可以從textbox繼承一個類,然後重寫wndpro,從而無視某些訊息。
最重要的訊息是WM_CHAR。此外,還有幾個特殊按鍵是永遠不能屏蔽的,分別是backspace, delete,此外還有快速鍵,ctrl-a,
ctrl-c,ctrl-x,ctrl-v.再此外,我們還要在執行粘貼時對文本做一次判斷,不合法文本則被忽略。
可以用一個FilterString的string來記錄合法字元,不在此字串中認為是不接受的字元,
/// <summary>
/// 覆蓋視窗過程!處理WM_CHAR訊息!
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
{
int charcode = (int)m.WParam;
switch (m.Msg)
{
case WM_CHAR:
// 遇到非法字元,直接return即可過濾非法字元!break表示處理該字元
//屏蔽小數點
if (charcode == (int)Keys.Decimal)
return;
// 注意delete,backspace字元不能過濾!!!
// ctrl-a,ctrl-c,ctrl-v快速鍵操作不能屏蔽!
if (charcode == (int)Keys.Back || charcode == (int)Keys.Delete)
break;
//如果按下了CTRL鍵
if (charcode == 1 //ctrl a
|| charcode == 3 //ctrl c
|| charcode == 22 //ctrl v
|| charcode == 24 //ctrl x
)
break;
if (this.m_FilterStr.IndexOf((char)charcode) < 0)
return;
break;
case WM_KEYDOWN:
//ctrl-A 全選
if (Control.ModifierKeys == Keys.Control)
{
if(charcode==(int)Keys.A)
this.SelectAll();
}
break;
case WM_PASTE:
//粘貼訊息
IDataObject obj = Clipboard.GetDataObject();
if (obj == null)
return;
if (obj.GetDataPresent(DataFormats.Text))
{
string text = obj.GetData(DataFormats.Text) as string;
if (text == null)
return;
foreach (char c in text)
{
//查看是否含有過濾字元以外的字元!
if (this.m_FilterStr.IndexOf(c) < 0)
return;
}
}
break;
}
//處理訊息
base.WndProc(ref m);
}
今天有些迷糊,主要是發現只處理wm_char時,ctrl-a快速鍵失效了,於是在keydown裡面手工實現了全選。具體原因也沒認真去研究,另外一個問題是發現對小數點的屏蔽‘.’無效,原因也不詳,好像按'.'的時候沒產生wm_char訊息就直接被處理掉了。鬱悶。先就這樣吧,不是很優美。