4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Copyright (c) 2007 Novell, Inc.
26 // Rolf Bjarne Kvinge (RKvinge@novell.com)
30 #if NET_2_0// && notyet
33 using System.Collections;
34 using System.ComponentModel;
36 using System.Drawing.Design;
37 using System.Globalization;
38 using System.Runtime.InteropServices;
39 using System.Security.Permissions;
40 using System.Windows.Forms;
42 namespace System.Windows.Forms
44 [ClassInterface (ClassInterfaceType.AutoDispatch)]
46 [DefaultProperty ("Mask")]
47 [DefaultEvent ("MaskInputRejected")]
48 [Designer ("System.Windows.Forms.Design.MaskedTextBoxDesigner, " + Consts.AssemblySystem_Design)]
49 [DefaultBindingProperty ("Text")]
50 public class MaskedTextBox : TextBoxBase
53 private MaskedTextProvider provider;
54 private bool beep_on_error;
55 private IFormatProvider format_provider;
56 private bool hide_prompt_on_leave;
57 private InsertKeyMode insert_key_mode;
58 private bool insert_key_overwriting;
59 private bool reject_input_on_first_failure;
60 private HorizontalAlignment text_align;
61 private MaskFormat cut_copy_mask_format;
62 private bool use_system_password_char;
63 private Type validating_type;
64 private bool is_empty_mask;
65 private bool setting_text;
69 static object AcceptsTabChangedEvent = new object ();
70 static object IsOverwriteModeChangedEvent = new object ();
71 static object MaskChangedEvent = new object ();
72 static object MaskInputRejectedEvent = new object ();
73 static object MultilineChangedEvent = new object ();
74 static object TextAlignChangedEvent = new object ();
75 static object TypeValidationCompletedEvent = new object ();
77 // This event is never raised by MaskedTextBox.
78 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
80 [EditorBrowsable (EditorBrowsableState.Never)]
81 public new event EventHandler AcceptsTabChanged {
82 add { Events.AddHandler (AcceptsTabChangedEvent, value);}
83 remove { Events.RemoveHandler (AcceptsTabChangedEvent, value);}
86 public event EventHandler IsOverwriteModeChanged {
87 add { Events.AddHandler (IsOverwriteModeChangedEvent, value); }
88 remove { Events.RemoveHandler (IsOverwriteModeChangedEvent, value); }
91 public event EventHandler MaskChanged {
92 add { Events.AddHandler (MaskChangedEvent, value); }
93 remove { Events.RemoveHandler (MaskChangedEvent, value); }
96 public event MaskInputRejectedEventHandler MaskInputRejected {
97 add { Events.AddHandler (MaskInputRejectedEvent, value); }
98 remove { Events.RemoveHandler (MaskInputRejectedEvent, value); }
101 // This event is never raised by MaskedTextBox.
102 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
104 [EditorBrowsable (EditorBrowsableState.Never)]
105 public new event EventHandler MultilineChanged {
106 add { Events.AddHandler (MultilineChangedEvent, value); }
107 remove { Events.RemoveHandler (MultilineChangedEvent, value); }
110 public event EventHandler TextAlignChanged {
111 add { Events.AddHandler (TextAlignChangedEvent, value); }
112 remove { Events.RemoveHandler (TextAlignChangedEvent, value); }
115 public event TypeValidationEventHandler TypeValidationCompleted {
116 add { Events.AddHandler (TypeValidationCompletedEvent, value); }
117 remove { Events.RemoveHandler (TypeValidationCompletedEvent, value); }
121 public MaskedTextBox ()
123 provider = new MaskedTextProvider ("<>", CultureInfo.CurrentCulture);
124 is_empty_mask = true;
128 public MaskedTextBox (MaskedTextProvider maskedTextProvider)
130 if (maskedTextProvider == null) {
131 throw new ArgumentNullException ();
133 provider = maskedTextProvider;
134 is_empty_mask = false;
138 public MaskedTextBox (string mask)
141 throw new ArgumentNullException ();
143 provider = new MaskedTextProvider (mask, CultureInfo.CurrentCulture);
144 is_empty_mask = false;
149 BackColor = SystemColors.Window;
150 cut_copy_mask_format = MaskFormat.IncludeLiterals;
151 UpdateVisibleText ();
154 #region Public and protected methods
155 [EditorBrowsable (EditorBrowsableState.Never)]
156 public new void ClearUndo ()
158 // Do nothing, not supported by MTB
161 [EditorBrowsable (EditorBrowsableState.Advanced)]
162 [UIPermission (SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
163 protected override void CreateHandle ()
165 base.CreateHandle ();
168 public override char GetCharFromPosition (Point pt)
170 return base.GetCharFromPosition (pt);
173 public override int GetCharIndexFromPosition (Point pt)
175 return base.GetCharIndexFromPosition (pt);
178 [EditorBrowsable (EditorBrowsableState.Never)]
179 public new int GetFirstCharIndexFromLine (int lineNumber)
184 [EditorBrowsable (EditorBrowsableState.Never)]
185 public new int GetFirstCharIndexOfCurrentLine ()
190 [EditorBrowsable (EditorBrowsableState.Never)]
191 public override int GetLineFromCharIndex (int index)
196 public override Point GetPositionFromCharIndex (int index)
198 return base.GetPositionFromCharIndex (index);
201 protected override bool IsInputKey (Keys keyData)
203 return base.IsInputKey (keyData);
206 protected override void OnBackColorChanged (EventArgs e)
208 base.OnBackColorChanged (e);
211 protected override void OnHandleCreated (EventArgs e)
213 base.OnHandleCreated (e);
216 [EditorBrowsable (EditorBrowsableState.Advanced)]
217 protected virtual void OnIsOverwriteModeChanged (EventArgs e)
219 EventHandler eh = (EventHandler) Events [IsOverwriteModeChangedEvent];
224 protected override void OnKeyDown (KeyEventArgs e)
229 protected override void OnKeyPress (KeyPressEventArgs e)
237 MaskedTextResultHint resultHint;
240 if (IsOverwriteMode) {
241 result = provider.InsertAt (e.KeyChar, SelectionStart, out testPosition, out resultHint);
243 result = provider.Replace (e.KeyChar, SelectionStart, SelectionStart, out testPosition, out resultHint);
247 OnMaskInputRejected (new MaskInputRejectedEventArgs (testPosition, resultHint));
249 int iIndex = provider.FindEditPositionFrom (SelectionStart+1, true);
251 if (iIndex != MaskedTextProvider.InvalidIndex) {
252 SelectionStart = iIndex;
254 SelectionStart = provider.Length;
257 UpdateVisibleText ();
263 protected override void OnKeyUp (KeyEventArgs e)
268 [EditorBrowsable (EditorBrowsableState.Advanced)]
269 protected virtual void OnMaskChanged (EventArgs e)
271 EventHandler eh = (EventHandler) Events [MaskChangedEvent];
276 private void OnMaskInputRejected (MaskInputRejectedEventArgs e)
278 MaskInputRejectedEventHandler eh = (MaskInputRejectedEventHandler) Events [MaskInputRejectedEvent];
283 [EditorBrowsable (EditorBrowsableState.Never)]
284 protected override void OnMultilineChanged (EventArgs e)
286 EventHandler eh = (EventHandler)Events [MultilineChangedEvent];
291 protected virtual void OnTextAlignChanged (EventArgs e)
293 EventHandler eh = (EventHandler)Events [TextAlignChangedEvent];
298 protected override void OnTextChanged (EventArgs e)
300 base.OnTextChanged (e);
303 [EditorBrowsable (EditorBrowsableState.Advanced)]
304 protected override void OnValidating (CancelEventArgs e)
306 base.OnValidating (e);
309 //[SecurityPermission (SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
310 protected override bool ProcessCmdKey (ref Message msg, Keys keyData)
312 return base.ProcessCmdKey (ref msg, keyData);
315 //[SecurityPermission (SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
316 protected internal override bool ProcessKeyMessage (ref Message m)
318 return base.ProcessKeyMessage (ref m);
321 [EditorBrowsable (EditorBrowsableState.Never)]
322 public new void ScrollToCaret ()
324 // MSDN: this method is overridden to perform no actions.
327 public override string ToString ()
329 return base.ToString () + ", Text: " + provider.ToString (false, false);
332 [EditorBrowsable (EditorBrowsableState.Never)]
333 public new void Undo ()
335 // Do nothing, not supported by MTB.
338 public object ValidateText ()
340 throw new NotImplementedException ();
343 //[SecurityPermission (SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
344 protected override void WndProc (ref Message m)
349 base.WndProc (ref m);
355 [EditorBrowsable (EditorBrowsableState.Never)]
356 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
358 public new bool AcceptsTab {
366 [DefaultValue (true)]
367 public bool AllowPromptAsInput {
369 return provider.AllowPromptAsInput;
372 provider = new MaskedTextProvider (provider.Mask, provider.Culture, value, provider.PromptChar, provider.PasswordChar, provider.AsciiOnly);
373 UpdateVisibleText ();
377 [RefreshProperties (RefreshProperties.Repaint)]
378 [DefaultValue (false)]
379 public bool AsciiOnly {
381 return provider.AsciiOnly;
384 provider = new MaskedTextProvider (provider.Mask, provider.Culture, provider.AllowPromptAsInput, provider.PromptChar, provider.PasswordChar, value);
385 UpdateVisibleText ();
389 [DefaultValue (false)]
390 public bool BeepOnError {
392 return beep_on_error;
395 beep_on_error = value;
400 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
401 [EditorBrowsable (EditorBrowsableState.Never)]
402 public new bool CanUndo {
408 protected override CreateParams CreateParams {
409 //[SecurityPermission (SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
411 return base.CreateParams;
415 [RefreshProperties (RefreshProperties.Repaint)]
416 public CultureInfo Culture {
418 return provider.Culture;
421 provider = new MaskedTextProvider (provider.Mask, value, provider.AllowPromptAsInput, provider.PromptChar, provider.PasswordChar, provider.AsciiOnly);
422 UpdateVisibleText ();
426 [RefreshProperties (RefreshProperties.Repaint)]
427 [DefaultValue (MaskFormat.IncludeLiterals)]
428 public MaskFormat CutCopyMaskFormat {
430 return cut_copy_mask_format;
433 if (!Enum.IsDefined (typeof (MaskFormat), value)) {
434 throw new InvalidEnumArgumentException ("value", (int)value, typeof (MaskFormat));
436 cut_copy_mask_format = value;
440 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
442 public IFormatProvider FormatProvider {
444 return format_provider;
447 format_provider = value;
451 [RefreshProperties (RefreshProperties.Repaint)]
452 [DefaultValue (false)]
453 public bool HidePromptOnLeave {
455 return hide_prompt_on_leave;
458 hide_prompt_on_leave = value;
462 [DefaultValue (InsertKeyMode.Default)]
463 public InsertKeyMode InsertKeyMode {
465 return insert_key_mode;
468 if (!Enum.IsDefined (typeof (InsertKeyMode), value)) {
469 throw new InvalidEnumArgumentException ("value", (int)value, typeof (InsertKeyMode));
471 insert_key_mode = value;
476 public bool IsOverwriteMode {
478 if (insert_key_mode == InsertKeyMode.Default) {
479 return insert_key_overwriting;
481 return insert_key_mode == InsertKeyMode.Overwrite;
486 [EditorBrowsable (EditorBrowsableState.Never)]
487 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
489 public new string [] Lines {
492 if (text == null || text == string.Empty)
493 return new string [] {};
495 return Text.Split (new string [] {"\r\n", "\r", "\n"}, StringSplitOptions.None);
498 // Do nothing, not supported by MTB.
503 [Editor ("System.Windows.Forms.Design.MaskPropertyEditor, " + Consts.AssemblySystem_Design, typeof (UITypeEditor))]
504 [RefreshProperties (RefreshProperties.Repaint)]
511 return provider.Mask;
514 is_empty_mask = (value == string.Empty || value == null);
519 provider = new MaskedTextProvider (value, provider.Culture, provider.AllowPromptAsInput, provider.PromptChar, provider.PasswordChar, provider.AsciiOnly);
520 ReCalculatePasswordChar ();
521 UpdateVisibleText ();
526 public bool MaskCompleted {
528 return provider.MaskCompleted;
533 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
534 public MaskedTextProvider MaskedTextProvider {
539 return provider.Clone () as MaskedTextProvider;
544 public bool MaskFull {
546 return provider.MaskFull;
550 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
552 [EditorBrowsable (EditorBrowsableState.Never)]
553 public override int MaxLength {
555 return base.MaxLength;
558 // Do nothing, MTB doesn't support this.
562 [EditorBrowsable (EditorBrowsableState.Never)]
564 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
565 public override bool Multiline {
570 // Do nothing, MTB doesn't support this.
574 [RefreshProperties (RefreshProperties.Repaint)]
575 [DefaultValue ('\0')]
576 public char PasswordChar {
578 if (use_system_password_char)
581 return provider.PasswordChar;
584 provider.PasswordChar = value;
587 provider.IsPassword = true;
589 provider.IsPassword = false;
591 ReCalculatePasswordChar (true);
592 CalculateDocument ();
594 UpdateVisibleText ();
600 [RefreshProperties (RefreshProperties.Repaint)]
601 public char PromptChar {
603 return provider.PromptChar;
606 provider.PromptChar = value;
607 UpdateVisibleText ();
611 public new bool ReadOnly {
613 return base.ReadOnly;
616 base.ReadOnly = value;
620 [DefaultValue (false)]
621 public bool RejectInputOnFirstFailure {
623 return reject_input_on_first_failure;
626 reject_input_on_first_failure = value;
630 [DefaultValue (true)]
631 public bool ResetOnPrompt {
633 return provider.ResetOnPrompt;
636 provider.ResetOnPrompt = value;
640 [DefaultValue (true)]
641 public bool ResetOnSpace {
643 return provider.ResetOnSpace;
646 provider.ResetOnSpace = value;
650 public override string SelectedText {
652 return base.SelectedText;
655 base.SelectedText = value;
656 UpdateVisibleText ();
660 [DefaultValue (true)]
661 public bool SkipLiterals {
663 return provider.SkipLiterals;
666 provider.SkipLiterals = value;
671 [Editor ("System.Windows.Forms.Design.MaskedTextBoxTextEditor, " + Consts.AssemblySystem_Design, typeof (UITypeEditor))]
673 [RefreshProperties (RefreshProperties.Repaint)]
675 public override string Text {
677 if (is_empty_mask || setting_text)
680 // The base constructor may call Text before we get to create a provider,
681 // so it may be null even though it's not an empty mask.
682 if (provider == null)
685 return provider.ToString ();
692 setting_text = false;
694 InputText (value, true, true);
696 UpdateVisibleText ();
700 [DefaultValue (HorizontalAlignment.Left)]
702 public HorizontalAlignment TextAlign {
707 if (text_align != value) {
708 if (!Enum.IsDefined (typeof (HorizontalAlignment), value)) {
709 throw new InvalidEnumArgumentException ("value", (int) value, typeof (HorizontalAlignment));
712 OnTextAlignChanged (EventArgs.Empty);
718 public override int TextLength {
724 [DefaultValue (MaskFormat.IncludeLiterals)]
725 [RefreshProperties (RefreshProperties.Repaint)]
726 public MaskFormat TextMaskFormat {
728 if (provider.IncludePrompt && provider.IncludeLiterals) {
729 return MaskFormat.IncludePromptAndLiterals;
730 } else if (provider.IncludeLiterals) {
731 return MaskFormat.IncludeLiterals;
732 } else if (provider.IncludePrompt) {
733 return MaskFormat.IncludePrompt;
735 return MaskFormat.ExcludePromptAndLiterals;
739 if (!Enum.IsDefined (typeof (MaskFormat), value)) {
740 throw new InvalidEnumArgumentException ("value", (int)value, typeof (MaskFormat));
743 provider.IncludeLiterals = (value & MaskFormat.IncludeLiterals) == MaskFormat.IncludeLiterals;
744 provider.IncludePrompt = (value & MaskFormat.IncludePrompt) == MaskFormat.IncludePrompt;
748 [DefaultValue (false)]
749 [RefreshProperties (RefreshProperties.Repaint)]
750 public bool UseSystemPasswordChar {
752 return use_system_password_char;
755 if (use_system_password_char != value) {
756 use_system_password_char = value;
758 if (use_system_password_char)
759 PasswordChar = PasswordChar;
766 [DefaultValue (null)]
768 public Type ValidatingType {
770 return validating_type;
773 validating_type = value;
776 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
778 [EditorBrowsable (EditorBrowsableState.Never)]
779 public new bool WordWrap {
784 // Do nothing, not supported by MTB
788 #region Internal and private members
790 private void ReCalculatePasswordChar ()
792 ReCalculatePasswordChar (PasswordChar != '\0');
795 private void ReCalculatePasswordChar (bool using_password)
799 document.PasswordChar = PasswordChar.ToString ();
801 document.PasswordChar = string.Empty;
804 internal override void OnPaintInternal (PaintEventArgs pevent)
806 base.OnPaintInternal (pevent);
807 //pevent.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), ClientRectangle);
808 //TextRenderer.DrawText (pevent.Graphics, Text, Font, ClientRectangle, ForeColor, TextFormatFlags.SingleLine);
809 //pevent.Handled = true;
812 internal override Color ChangeBackColor (Color backColor)
817 private void UpdateVisibleText ()
821 if (is_empty_mask || setting_text)
824 if (provider == null)
827 text = provider.ToDisplayString ();
830 if (base.Text != text) {
831 int selstart = SelectionStart;
833 SelectionStart = selstart;
835 setting_text = false;
838 private void InputText (string text, bool overwrite, bool clear)
847 MaskedTextResultHint resultHint;
850 if (RejectInputOnFirstFailure) {
852 provider.Replace (input, SelectionStart, SelectionStart + SelectionLength, out testPosition, out resultHint);
854 provider.InsertAt (input, SelectionStart);
857 while (!result && input.Length > 0) {
859 result = provider.Replace (input, SelectionStart, SelectionStart + input.Length, out testPosition, out resultHint);
861 result = provider.InsertAt (input, SelectionStart, out testPosition, out resultHint);
868 input = input.Substring (0, Math.Min(testPosition - SelectionStart - 1, input.Length - 1));