經常某些輸入的文本要求隻能是數字等,比如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
)
if (this.m_FilterStr.IndexOf((char)charcode) < 0)
break;
case WM_KEYDOWN:
//ctrl-A 全選
if (Control.ModifierKeys == Keys.Control)
{
if(charcode==(int)Keys.A)
this.SelectAll();
}
case WM_PASTE:
//粘貼消息
IDataObject obj = Clipboard.GetDataObject();
if (obj == null)
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;
}
}
//處理消息
base.WndProc(ref m);
}
今天有些迷糊,主要是發現隻處理wm_char時,ctrl-a快捷鍵失效了,于是在keydown裡面手工實作了全選。具體原因也沒認真去研究,另外一個問題是發現對小數點的屏蔽‘.’無效,原因也不詳,好像按'.'的時候沒産生wm_char消息就直接被處理掉了。郁悶。先就這樣吧,不是很優美。