2013-01-21 50 views
2

在我的窗口應用程序中,我需要蒙面文本框,它接受真正的十進制數字。帶十進制數字的蒙面文本框

例如,
1)1.56
2)22.34
3)123.34
4)12312.34
這所有值應該是有效的。

有誰能告訴我該怎麼辦?
而雅如果有人有更好的解決方案,真正的小數,而不是這個蒙面文本框 比我喜歡看到它。
謝謝...

+0

所有你的例子有兩位小數。你會想要接受更多的數字嗎? – Dai

+0

不,只有兩個... –

回答

3

使用自定義控制像這樣的(修改,以滿足您的需要):

using System; 
using System.ComponentModel; 
using System.Text; 
using System.Windows.Forms; 
using System.Drawing; 

namespace CustomControls 
{ 
    public enum PasteRejectReasons 
    { 
     Unknown = 0, 
     NoData, 
     InvalidCharacter, 
     Accepted 
    } 

    public class DecimalTextBox : TextBox 
    { 
     public const int WM_PASTE = 0x0302; 
     public event EventHandler<KeyRejectedEventArgs> KeyRejected; 
     public event EventHandler<PasteEventArgs> PasteRejected; 

     private bool _DecimalSeparator = false; 
     private int _Precision; 

     public new HorizontalAlignment TextAlign 
     { 
      get { return base.TextAlign; } 
      set { base.TextAlign = value; } 
     } 

     public int Precision 
     { 
      get { return _Precision; } 
      set { _Precision = value; } 
     } 

     public DecimalTextBox() 
     { 
      TextAlign = HorizontalAlignment.Right; 
      Precision = 3; 
     } 

     protected override void OnGotFocus(EventArgs e) 
     { 
      SelectAll(); 
      base.OnGotFocus(e); 
     } 

     protected override void OnKeyDown(KeyEventArgs e) 
     { 
      bool validate = true; 

      if (Text.Contains(".") || Text.Contains(",")) 
      { 
       int indexSep; 
       string[] split; 
       string partiDecimal = ""; 

       if (Text.Contains(".")) 
        indexSep = Text.IndexOf('.'); 
       else 
        indexSep = Text.IndexOf(','); 

       split = Text.Split(new char[] { ',', '.' }); 
       partiDecimal += split[1]; 

       if (partiDecimal.Length >= Precision) 
        if (SelectionStart > Text.Length - (partiDecimal.Length + 1)) 
         validate = false; 
      } 

      bool result = true; 

      bool validateKeys = (e.KeyCode == Keys.Enter); 

      bool numericKeys = ( 
       ((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) || 
       (e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9)) 
       && e.Modifiers != Keys.Shift 
       && validate); 

      bool ctrlA = e.KeyCode == Keys.A && e.Modifiers == Keys.Control; 

      bool editKeys = ( 
       (e.KeyCode == Keys.Z && e.Modifiers == Keys.Control) || 
       (e.KeyCode == Keys.X && e.Modifiers == Keys.Control) || 
       (e.KeyCode == Keys.C && e.Modifiers == Keys.Control) || 
       (e.KeyCode == Keys.V && e.Modifiers == Keys.Control) || 
       e.KeyCode == Keys.Delete || 
       e.KeyCode == Keys.Back); 

      bool navigationKeys = ( 
       e.KeyCode == Keys.Up || 
       e.KeyCode == Keys.Right || 
       e.KeyCode == Keys.Down || 
       e.KeyCode == Keys.Left || 
       e.KeyCode == Keys.Home || 
       e.KeyCode == Keys.End); 

      bool decimalSeparator = (( 
       e.KeyCode == Keys.Decimal || 
       e.KeyValue == 190 || 
       e.KeyValue == 188)&& 
       TextLength != 0 && 
       SelectionLength == 0); 

      if (decimalSeparator) 
      { 
       if (!_DecimalSeparator) 
        _DecimalSeparator = true; 
       else 
        decimalSeparator = false; 
      } 

      if (!(numericKeys || editKeys || navigationKeys || decimalSeparator || validateKeys)) 
      { 
       if (ctrlA) 
        SelectAll(); 

       result = false; 
      } 

      if (!result) 
      { 
       e.SuppressKeyPress = true; 
       e.Handled = true; 

       if (!ctrlA) 
        OnKeyRejected(new KeyRejectedEventArgs(e.KeyCode)); 
      } 
      else 
       base.OnKeyDown(e); 
     } 

     protected override void OnKeyPress(KeyPressEventArgs e) 
     { 
      if (e.KeyChar == ';' || e.KeyChar == '?') 
      { 
       if (!(Text.Contains(",") || Text.Contains("."))) 
        _DecimalSeparator = false; 
       e.Handled = true; 
      } 
     } 

     protected override void OnTextChanged(EventArgs e) 
     { 
      bool invalid = false; 
      int i = 0; 
      foreach (char c in Text) // Check for any non digit characters. 
      { 
       if (!(char.IsDigit(c) || c == ',' || c == '.')) 
       { 
        invalid = true; 
        break; 
       } 

       if (c == ',' || c == '.') 
        i++; 
      } 

      if (i == 0) 
       _DecimalSeparator = false; 
      else if (i > 1) 
       invalid = true; 

      if (invalid) 
      { 
       Text = ""; 
       return; 
      } 

      if (Text.Contains(".") || Text.Contains(",")) 
      { 
       string charSep = ""; 
       string[] split; 
       string partiEntier = ""; 

       if (Text.Contains(".")) 
        charSep = "."; 
       else 
        charSep = ","; 

       split = Text.Split(new char[] { ',', '.' }); 
       partiEntier += split[0]; 
       if (partiEntier == "") 
        Text = "0" + charSep + split[1]; 
      } 
      base.OnTextChanged(e); 
     } 

     protected override void WndProc(ref Message m) 
     { 
      if (m.Msg == WM_PASTE) 
      { 
       PasteEventArgs e = CheckPasteValid(); 
       if (e.RejectReason != PasteRejectReasons.Accepted) 
       { 
        m.Result = IntPtr.Zero; 
        OnPasteRejected(e); 
        return; 
       } 
      } 
      base.WndProc(ref m); 
     } 

     private PasteEventArgs CheckPasteValid() 
     { 
      PasteRejectReasons rejectReason = PasteRejectReasons.Accepted; 
      string originalText = Text; 
      string clipboardText = string.Empty; 
      string textResult = string.Empty; 

      try 
      { 
       clipboardText = Clipboard.GetText(TextDataFormat.Text); 
       if (clipboardText.Length > 0) 
       { 

        textResult = ( 
         Text.Remove(SelectionStart, SelectionLength).Insert(SelectionStart, clipboardText)); 
        foreach (char c in clipboardText) 
        { 
         if (!char.IsDigit(c)) 
         { 
          rejectReason = PasteRejectReasons.InvalidCharacter; 
          break; 
         } 
        } 
       } 
       else 
        rejectReason = PasteRejectReasons.NoData; 
      } 
      catch 
      { 
       rejectReason = PasteRejectReasons.Unknown; 
      } 
      return new PasteEventArgs(originalText, clipboardText, textResult, rejectReason); 
     } 

     protected virtual void OnKeyRejected(KeyRejectedEventArgs e) 
     { 
      EventHandler<KeyRejectedEventArgs> handler = KeyRejected; 
      if (handler != null) 
       handler(this, e); 
     } 

     protected virtual void OnPasteRejected(PasteEventArgs e) 
     { 
      EventHandler<PasteEventArgs> handler = PasteRejected; 
      if (handler != null) 
       handler(this, e); 
     } 
    } 
} 
+1

+1尚未嘗試過,但看起來很棒。我有一天看到了一些很好的代碼,謝謝分享。 –

+0

你有KeyRejectedEventArgs和PasteEventArgs的定義嗎? – Gandarez

+0

小心國外文化本土化。在許多國家,逗號和句號的數字都是千位數和小數點。這段代碼非常暴力,可能會讓你在尾巴中咬人。 – XKCD137

7

而不是使用MaskedTextbox,請考慮使用NumericUpDown來代替。它支持System.Decimal數字,它支持你應該關心的大多數實際數字。

NumericUpDown.DecimalPlaces屬性支持多達99個小數位。

+0

如何從100增加NumericUpDown的最大值? –

+0

單擊向上/向下控件,按F4調出其屬性並將最大屬性從100增加。 –