Masked Textbox

  • Thread starter DazedAndConfused
  • Start date
D

DazedAndConfused

Curently I manualy code keypress edits. i.e. allow only 3 digits before
decimal and two digits after decimal in .NET.

Is there an easy solution to mask text boxes?

The MSMASK32.OCX from vb6 does not seem to be appropriate for a desktop
application with textboxes not bound to a dataset, am I wrong?
 
H

Herfried K. Wagner [MVP]

DazedAndConfused said:
Curently I manualy code keypress edits. i.e. allow only 3 digits before
decimal and two digits after decimal in .NET.

Is there an easy solution to mask text boxes?

<URL:http://www.codeproject.com/cs/miscctrl/maskedcsedit.asp>
<URL:http://www.codeproject.com/vb/net/maskedbox_control.asp>
<URL:http://www.codeproject.com/vb/net/validtext3.asp>
<URL:http://www.codeproject.com/vb/net/cpflexmaskeditbox.asp>
<URL:http://www.codeproject.com/useritems/ValidText.asp>
....

..NET 2.0 will contain a masked edit control.

In some situation using an ErrorProvider to make the user aware of malformed
input can be more appropriate:

Validator Controls for Windows Forms
The MSMASK32.OCX from vb6 does not seem to be appropriate for a desktop
application with textboxes not bound to a dataset, am I wrong?

You are wrong.
 
D

DazedAndConfused

Thank you.

I don't know a lot about VB6 (or .NET for that matter), when I used the
masked edit control (MSMASK32.OCX) in .NET I couldn't find a property that
mapped to the modified property in VB .NET, is there already a way to check
for modified in VB6 (I thought of ways to get around it, just wondered if I
missed a clear cut way).
 
J

Jack Russell

DazedAndConfused said:
Curently I manualy code keypress edits. i.e. allow only 3 digits before
decimal and two digits after decimal in .NET.

Is there an easy solution to mask text boxes?

The MSMASK32.OCX from vb6 does not seem to be appropriate for a desktop
application with textboxes not bound to a dataset, am I wrong?
Try Farpoints Inputpro

A satisfied customer
 
H

Herfried K. Wagner [MVP]

DazedAndConfused said:
I don't know a lot about VB6 (or .NET for that matter), when I used the
masked edit control (MSMASK32.OCX) in .NET I couldn't find a property that
mapped to the modified property in VB .NET, is there already a way to
check for modified in VB6 (I thought of ways to get around it, just
wondered if I missed a clear cut way).

You'll have to implement this behaviour on your own.
 
G

Guest

Try this control:

Imports System.Object
Imports System.Text

Public Class MultiEdit
Inherits System.Windows.Forms.TextBox

'Mask Edit Control:
' # = Digits
' @ = Any Alpha
' ^ = UpperCase Alpha
' ! = Digits or Alpha
' ~ = Digits or Upper Case Alpha

Private v_entryfieldchar As Char = "_"c
Private bolDelete As Boolean
Private pass As Boolean
Private v_Mask As String = ""
Private mParams() As Char = {("&"c), ("#"c), ("!"c), ("^"c), ("~"c)}

#Region " Component Designer generated code "

Public Sub New(ByVal Container As System.ComponentModel.IContainer)
MyClass.New()

'Required for Windows.Forms Class Composition Designer support
Container.Add(Me)
End Sub

Public Sub New()
MyBase.New()

'This call is required by the Component Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Component overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Component Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Component Designer
'It can be modified using the Component Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
'
'MultiEdit
'
Me.Font = New System.Drawing.Font("Tahoma", 8.25!,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0,
Byte))

End Sub

#End Region

Public ReadOnly Property UnformatedText() As String
Get
Dim i As Integer
Dim strText As String = ""
For i = 0 To v_Mask.Length - 1
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 AndAlso
Me.Text.Chars(i) <> v_entryfieldchar Then
strText += Me.Text.Chars(i)
End If
Next
Return strText
End Get
End Property
Public Property EntryFieldChar() As Char
Get
Return v_entryfieldchar
End Get
Set(ByVal Value As Char)
v_entryfieldchar = Value
Me.Mask = v_Mask
End Set
End Property

Public Property Mask() As String
Get
Return (v_Mask)
End Get
Set(ByVal Value As String)
v_Mask = Value
Dim a As String = v_Mask
a = a.Replace("#", v_entryfieldchar).Replace("&",
v_entryfieldchar).Replace("!", v_entryfieldchar).Replace("^",
v_entryfieldchar).Replace("~", v_entryfieldchar)
MyBase.Text = a
End Set
End Property
Public Overrides Property Text() As String
Get
Return MyBase.Text
End Get
Set(ByVal Value As String)
If v_Mask Is Nothing OrElse v_Mask.Length <= 0 Then
MyBase.Text = ""
Exit Property
End If
Dim i, k As Integer
Dim a As Char
Dim strtext As New StringBuilder
Dim arr() As Char = Value.ToCharArray()
For i = 0 To v_Mask.Length - 1
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
a = ControlChars.NullChar
While k < arr.Length
a = IsValidChar(v_Mask.Chars(i), arr(k))
k = k + 1
If a <> ControlChars.NullChar Then Exit While
End While
If a <> ControlChars.NullChar Then
strtext.Append(a)
Else
strtext.Append(v_entryfieldchar)
End If
Else
strtext.Append(v_Mask.Chars(i))
End If
Next
MyBase.Text = strtext.ToString
End Set
End Property
Private Function IsValidChar(ByVal MaskChar As Char, ByVal c As Char) As
Char
Dim valid As Boolean
Select Case True
Case Char.IsLetter(c)
If MaskChar = "&" OrElse MaskChar = "!" Then
valid = True
ElseIf MaskChar = "^" OrElse MaskChar = "~" Then
c = Char.ToUpper(c)
valid = True
End If
Case Char.IsDigit(c)
If MaskChar = "#" OrElse MaskChar = "!" OrElse MaskChar =
"~" Then
valid = True
End If
End Select
If valid Then
Return c
Else
Return ControlChars.NullChar
End If
End Function

Protected Overrides Sub OnKeyDown(ByVal e As
System.Windows.Forms.KeyEventArgs)
'Disables Delete Key
If v_Mask Is Nothing OrElse v_Mask.Length <= 0 Then e.Handled = True
: Exit Sub
If e.KeyCode = Keys.Delete Then
e.Handled = True
Dim selstart As Integer = Me.SelectionStart
If selstart < v_Mask.Length Then
Dim i As Integer
Dim strText As String = Me.Text
Dim delto As Integer
If Me.SelectionLength = 0 Then delto = selstart Else delto =
Me.SelectionStart + Me.SelectionLength - 1
For i = selstart To delto
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
strText = strText.Remove(i, 1).Insert(i,
v_entryfieldchar)
End If
Next
MyBase.Text = strText
Me.SelectionStart = selstart
Me.SelectionLength = 0
End If
Else
MyBase.OnKeyDown(e)
End If
End Sub

Protected Overrides Sub OnKeyPress(ByVal e As
System.Windows.Forms.KeyPressEventArgs)
'key pressed
Dim chrKeyPressed As Char = e.KeyChar
'Original cursor position
Dim intSelStart As Integer = Me.SelectionStart
'In case of a selection, delete text to this position
Dim intDelTo As Integer = Me.SelectionStart + Me.SelectionLength - 1
Dim strText As String = Me.Text
Dim i As Integer
Dim c As Char
'Used to avoid deletion of the selection when an invalid key is
pressed
bolDelete = False : pass = False
e.Handled = True

'Find the Next Insertion point
'Test char to pass the # or @ or ^ or ~ or "^" or "~" test
'Mask:
' # = Digits
' @ = Any Alpha
' ^ = UpperCase Alpha
' ! = Digits or Alpha
' ~ = Digits or Upper Case Alpha

If chrKeyPressed = ControlChars.Back AndAlso Me.SelectionStart =
v_Mask.Length Then
For i = v_Mask.Length - 1 To 0 Step -1
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
strText = strText.Remove(i, 1).Insert(i, v_entryfieldchar)
MyBase.Text = strText
Me.SelectionStart = i
Me.SelectionLength = 0
Exit For
End If
Next
Exit Sub
End If

For i = Me.SelectionStart To v_Mask.Length - 1
bolDelete = False
Select Case True
Case chrKeyPressed = ControlChars.Back
bolDelete = True
If intSelStart > 0 And intDelTo < intSelStart Then
intSelStart -= 1
End If
Case Else
c = IsValidChar(v_Mask.Chars(i), chrKeyPressed)
pass = c <> ControlChars.NullChar
End Select
If pass Then
strText = strText.Remove(i, 1).Insert(i, c)
intSelStart = i + 1
bolDelete = True
End If

'Prevent looping unitl the next available match when mixing # &
! on the same mask
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
Exit For
End If
Next

'Delete remaining chars from selection or previous char if backspace
If bolDelete Then
For i = intSelStart To intDelTo
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
strText = strText.Remove(i, 1).Insert(i, v_entryfieldchar)
End If
Next
MyBase.Text = strText
Me.SelectionStart = intSelStart
Me.SelectionLength = 0
End If
End Sub
Public Overrides Property MultiLine() As Boolean
Get
Return False
End Get
Set(ByVal Value As Boolean)
MyBase.Multiline = False
End Set
End Property
End Class
--
Dennis in Houston


DazedAndConfused said:
Thank you.

I don't know a lot about VB6 (or .NET for that matter), when I used the
masked edit control (MSMASK32.OCX) in .NET I couldn't find a property that
mapped to the modified property in VB .NET, is there already a way to check
for modified in VB6 (I thought of ways to get around it, just wondered if I
missed a clear cut way).
 
A

Aaron Smith

DazedAndConfused said:
Curently I manualy code keypress edits. i.e. allow only 3 digits before
decimal and two digits after decimal in .NET.

Is there an easy solution to mask text boxes?

The MSMASK32.OCX from vb6 does not seem to be appropriate for a desktop
application with textboxes not bound to a dataset, am I wrong?

From what I had experianced, in .Net 1.1 you have to make your own to
do that. In .Net 2.0 the masked edit control is back and it works
extremely well. I created my own classes for doing what we needed to do,
which was phone numbers and social security numbers... Then we switched
everything over to .Net 2.0 because a lot of stuff we do was made easier
in it... It made all the work I did on custom classes completely
obsolete, but at least it's in there for anything else we will have to do...
 
D

DazedAndConfused

Thank you. Actualy (please correct me if I'm wrong), I have found the edit
masks force you to account for all positions in a numeric field before the
decimal point, i.e. 99.99 in a masked field of "###.##" you must enter
either "_ 99.99" or "099.99", entering the decimal after "99____" does
nothing, I want the functionality to allow entering "99.99" even if the
field is masked as "###.##.

I'm a mainframer, and want something that works like a pic 999V99.

So, I'm writting it now.

If I have something wrong, let me know, I'm new.

--
How time fly's when you don't know what you are doing!
I learn when I'm wrong, I learn a lot.
Dennis said:
Try this control:

Imports System.Object
Imports System.Text

Public Class MultiEdit
Inherits System.Windows.Forms.TextBox

'Mask Edit Control:
' # = Digits
' @ = Any Alpha
' ^ = UpperCase Alpha
' ! = Digits or Alpha
' ~ = Digits or Upper Case Alpha

Private v_entryfieldchar As Char = "_"c
Private bolDelete As Boolean
Private pass As Boolean
Private v_Mask As String = ""
Private mParams() As Char = {("&"c), ("#"c), ("!"c), ("^"c), ("~"c)}

#Region " Component Designer generated code "

Public Sub New(ByVal Container As System.ComponentModel.IContainer)
MyClass.New()

'Required for Windows.Forms Class Composition Designer support
Container.Add(Me)
End Sub

Public Sub New()
MyBase.New()

'This call is required by the Component Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Component overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Component Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Component Designer
'It can be modified using the Component Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
'
'MultiEdit
'
Me.Font = New System.Drawing.Font("Tahoma", 8.25!,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
CType(0,
Byte))

End Sub

#End Region

Public ReadOnly Property UnformatedText() As String
Get
Dim i As Integer
Dim strText As String = ""
For i = 0 To v_Mask.Length - 1
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 AndAlso
Me.Text.Chars(i) <> v_entryfieldchar Then
strText += Me.Text.Chars(i)
End If
Next
Return strText
End Get
End Property
Public Property EntryFieldChar() As Char
Get
Return v_entryfieldchar
End Get
Set(ByVal Value As Char)
v_entryfieldchar = Value
Me.Mask = v_Mask
End Set
End Property

Public Property Mask() As String
Get
Return (v_Mask)
End Get
Set(ByVal Value As String)
v_Mask = Value
Dim a As String = v_Mask
a = a.Replace("#", v_entryfieldchar).Replace("&",
v_entryfieldchar).Replace("!", v_entryfieldchar).Replace("^",
v_entryfieldchar).Replace("~", v_entryfieldchar)
MyBase.Text = a
End Set
End Property
Public Overrides Property Text() As String
Get
Return MyBase.Text
End Get
Set(ByVal Value As String)
If v_Mask Is Nothing OrElse v_Mask.Length <= 0 Then
MyBase.Text = ""
Exit Property
End If
Dim i, k As Integer
Dim a As Char
Dim strtext As New StringBuilder
Dim arr() As Char = Value.ToCharArray()
For i = 0 To v_Mask.Length - 1
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
a = ControlChars.NullChar
While k < arr.Length
a = IsValidChar(v_Mask.Chars(i), arr(k))
k = k + 1
If a <> ControlChars.NullChar Then Exit While
End While
If a <> ControlChars.NullChar Then
strtext.Append(a)
Else
strtext.Append(v_entryfieldchar)
End If
Else
strtext.Append(v_Mask.Chars(i))
End If
Next
MyBase.Text = strtext.ToString
End Set
End Property
Private Function IsValidChar(ByVal MaskChar As Char, ByVal c As Char)
As
Char
Dim valid As Boolean
Select Case True
Case Char.IsLetter(c)
If MaskChar = "&" OrElse MaskChar = "!" Then
valid = True
ElseIf MaskChar = "^" OrElse MaskChar = "~" Then
c = Char.ToUpper(c)
valid = True
End If
Case Char.IsDigit(c)
If MaskChar = "#" OrElse MaskChar = "!" OrElse MaskChar =
"~" Then
valid = True
End If
End Select
If valid Then
Return c
Else
Return ControlChars.NullChar
End If
End Function

Protected Overrides Sub OnKeyDown(ByVal e As
System.Windows.Forms.KeyEventArgs)
'Disables Delete Key
If v_Mask Is Nothing OrElse v_Mask.Length <= 0 Then e.Handled =
True
: Exit Sub
If e.KeyCode = Keys.Delete Then
e.Handled = True
Dim selstart As Integer = Me.SelectionStart
If selstart < v_Mask.Length Then
Dim i As Integer
Dim strText As String = Me.Text
Dim delto As Integer
If Me.SelectionLength = 0 Then delto = selstart Else delto
=
Me.SelectionStart + Me.SelectionLength - 1
For i = selstart To delto
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
strText = strText.Remove(i, 1).Insert(i,
v_entryfieldchar)
End If
Next
MyBase.Text = strText
Me.SelectionStart = selstart
Me.SelectionLength = 0
End If
Else
MyBase.OnKeyDown(e)
End If
End Sub

Protected Overrides Sub OnKeyPress(ByVal e As
System.Windows.Forms.KeyPressEventArgs)
'key pressed
Dim chrKeyPressed As Char = e.KeyChar
'Original cursor position
Dim intSelStart As Integer = Me.SelectionStart
'In case of a selection, delete text to this position
Dim intDelTo As Integer = Me.SelectionStart + Me.SelectionLength -
1
Dim strText As String = Me.Text
Dim i As Integer
Dim c As Char
'Used to avoid deletion of the selection when an invalid key is
pressed
bolDelete = False : pass = False
e.Handled = True

'Find the Next Insertion point
'Test char to pass the # or @ or ^ or ~ or "^" or "~" test
'Mask:
' # = Digits
' @ = Any Alpha
' ^ = UpperCase Alpha
' ! = Digits or Alpha
' ~ = Digits or Upper Case Alpha

If chrKeyPressed = ControlChars.Back AndAlso Me.SelectionStart =
v_Mask.Length Then
For i = v_Mask.Length - 1 To 0 Step -1
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
strText = strText.Remove(i, 1).Insert(i,
v_entryfieldchar)
MyBase.Text = strText
Me.SelectionStart = i
Me.SelectionLength = 0
Exit For
End If
Next
Exit Sub
End If

For i = Me.SelectionStart To v_Mask.Length - 1
bolDelete = False
Select Case True
Case chrKeyPressed = ControlChars.Back
bolDelete = True
If intSelStart > 0 And intDelTo < intSelStart Then
intSelStart -= 1
End If
Case Else
c = IsValidChar(v_Mask.Chars(i), chrKeyPressed)
pass = c <> ControlChars.NullChar
End Select
If pass Then
strText = strText.Remove(i, 1).Insert(i, c)
intSelStart = i + 1
bolDelete = True
End If

'Prevent looping unitl the next available match when mixing # &
! on the same mask
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
Exit For
End If
Next

'Delete remaining chars from selection or previous char if
backspace
If bolDelete Then
For i = intSelStart To intDelTo
If Array.IndexOf(mParams, v_Mask.Chars(i)) > -1 Then
strText = strText.Remove(i, 1).Insert(i,
v_entryfieldchar)
End If
Next
MyBase.Text = strText
Me.SelectionStart = intSelStart
Me.SelectionLength = 0
End If
End Sub
Public Overrides Property MultiLine() As Boolean
Get
Return False
End Get
Set(ByVal Value As Boolean)
MyBase.Multiline = False
End Set
End Property
End Class
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top