C# TextBox中只允許輸入數位解決方案

來源:互聯網
上載者:User

來源:中國自學編程網收集整理  
發布日期:2008-12-02  

 

       
最近看到一些關於TextBox中限制只允許輸入數位博文,這類問題常常用事後處理模式:錄入字元結束後在控制項離開(如Exit事件)或確認時進行判斷。本文探討控制項錄入操作的事前處理模式:做錄入操作時屏蔽非數字字元。下面,結合筆者前段時間修改完善的開源數值文框TNumEditBox控制項,介紹一個基於定製TextBox控制項的解決方案。 

       
在定製的TextBox控制項中,如果只允許輸入數字,需要考慮如下三種情況: 
       
1).正常按鍵輸入的字元,包括西文、中文字元等 
        2).通過鍵盤快速鍵方式貼入的文本,即Ctrl+V操作 
       
3).通過上下文關聯菜單的Mouse操作貼入的文本,即”粘貼“操作 
       
在探討的同類文章中,多數只考慮了第1種情況,忽略得了第2、3種常見的操作。本文探討的處理方法核心思路是重寫事件OnKeyPress()和兩個方法
ProcessCmdKey()與WndProc(),並把Ctrl+V、關聯菜單的Paste操作統一到鍵盤錄入操作中,從而在
OnKeyPress()屏蔽掉非數字鍵。

1、重寫鍵盤事件OnKeyPress()
 
       
鍵盤輸入的字元可以通過重寫TextBox控制項的OnKeyPress()事件處理,見如下代碼:

        protected override void
OnKeyPress(KeyPressEventArgs e) // 屏蔽非數字鍵

        {

                 base.OnKeyPress(e);

                 if (this.ReadOnly) // 唯讀, 不處理

                         return;

                if ((int)e.KeyChar <= 32) //
特殊鍵(含空格), 不處理 

                         return;

                if (!char.IsDigit(e.KeyChar)) //
非數字鍵, 放棄該輸入

                {

                         e.Handled = true;

                        return;

                }

        }



2、重寫命令鍵處理方法ProcessCmdKey()
 
       
可以在ProcessCmdKey()中捕獲快速鍵Ctrl+V操作。首先要清除當前的選擇文本,然後讀取剪下板ClipBoard中的內容,最後通過類比鍵盤輸入的方式”輸入“ClipBoard的內容。需要指出,在ProcessCmdKey()方法中不能使用靜態方法
SendKeys.Send(),但可以通過控制項的WndProc()方法發送字元訊息以達到類比鍵盤錄入的目的。見如下代碼: 
       
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) //
捕獲Ctrl+V

        {

                 if (keyData == (Keys)Shortcut.CtrlV) // 快速鍵 Ctrl+V 粘貼操作

                {

                         this.ClearSelection();

                         string text = Clipboard.GetText();

                          for (int k = 0; k < text.Length; k++) // can not
use SendKeys.Send

                         { // 通過訊息類比鍵盤輸入, SendKeys.Send()靜態方法不行

                                 SendCharKey(text[k]);

                          }

                        return true;

                }

                 return base.ProcessCmdKey(ref msg, keyData);

        }

 

        private void SendCharKey(char c) // 通過訊息類比鍵盤錄入

        {

                Message msg = new Message();

                msg.HWnd = this.Handle;

                msg.Msg = WM_CHAR; // 輸入鍵盤字元訊息

                msg.WParam = (IntPtr)c;

                 msg.LParam = IntPtr.Zero;

                base.WndProc(ref msg);

        }


3、重寫訊息處理方法WndProc()
 
       
可以在定製TextBox控制項中建立無內容的操作功能表對象,從而屏蔽該菜單,方法是在定製控制項的建構函式中增加如下代碼: 
        public
class CustomTextBox : TextBox

        { // 建立無內容菜單對象, 等價屏蔽該控制項的操作功能表

                this.ContextMenu = new ConTextMenu();

        }

        由於操作功能表的Paste操作對應Windows的WM_PASTE訊息,於是可以在控制項的WndProc()方法中捕獲該訊息,然後獲得剪下板
ClipBoard中的內容,最後通過SendKeys.Send()方法類比鍵盤錄入操作。需要注意,這裡不能調用前面ProcessCmdKey()
中類比鍵盤輸入函數SendCharKey()。見如下代碼: 
        protected override void WndProc(ref
Message m) // 捕獲Mouse的Paste訊息

        {

                if (m.Msg == WM_PASTE) // 選擇操作功能表的"粘貼"操作

                {

                         this.ClearSelection();

                        SendKeys.Send(Clipboard.GetText()); // 類比鍵盤輸入

                }

                else

                 {

                         base.WndProc(ref m);

                }

        }


4、消除選擇ClearSelection()、刪除字元DeleteText() 

       
還必須分析前面代碼中的兩個函數: 
       
ClearSelection()用以清除當前的選擇文本,即清除this.SelectedText 
       
DeleteText()則刪除當前字元 
       
需要指出其中的技巧,就是轉換Delete鍵操作為BackSpace操作。此外,函數DeleteText()還需要確定當前的this.SelectionStart值。具體代碼如下: 
       
private void ClearSelection() // 清除當前TextBox的選擇

        {

                 if (this.SelectionLength == 0)

                         return;

                 int selLength = this.SelectedText.Length;

                 this.SelectionStart += this.SelectedText.Length; // 游標在選擇之後

                 this.SelectionLength = 0;

                 for (int k = 1; k <= selLength; k++)

                         this.DeleteText(Keys.Back);

        }

 

        private void DeleteText(Keys key) // 刪除字元並計算SelectionStart值

        {

                  int selStart = this.SelectionStart;

                 if (key == Keys.Delete) // 轉換Delete操作為BackSpace操作

                 {

                         selStart += 1;

                         if (selStart > base.Text.Length)

                                  return;

                 }

                 if (selStart == 0 || selStart > base.Text.Length) //
不需要刪除

                         return; 

                  if (selStart == 1 && base.Text.Length == 1)

                 {

                         base.Text = "";

                         base.SelectionStart = 0;

                 }

                 else // selStart > 0

                 {

                          base.Text = base.Text.Substring(0, selStart - 1) +
base.Text.Substring(selStart, base.Text.Length - selStart);

                         base.SelectionStart = selStart - 1;

                 }

        }


5、結語 

       
本文探討的是TextBox控制項輸入的事前處理模式,即在輸入字元的同時屏蔽非數字鍵。在實際應用中一般採取事後處理模式,即在TextBox控制項的
Exit、Validate等事件中進行輸入後處理——離開該控時進行驗證。但事後處理模式有如下不足: 
       
與資料來源綁定時輸入非數字字元可能拋出異常,需要考慮異常捕獲 
        需要判斷資料並給出錯誤提示等處理 

       
上述內容是從筆者的開源數值型資料編輯控制項TNumEditBox中修改刪減而來的,該控制項考慮的情況比只允許數字輸入要複雜得多,感興趣者可以參考並指正。需要指出,TNumEditBox的核心思路來自免費的Delphi控制項PBNumEdit和開源的C#控制項BANumEdit。作為回報,筆者也將
TNumEditBox開源並發布到CodeProject。
       
這裡探討的是屏蔽非數字鍵輸入,顯然可以推廣到屏蔽其它特殊鍵如Tab和指定字母等。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.