Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Smart textbox formatting

Status
Not open for further replies.

EagleTempest

Technical User
Jun 15, 2004
125
CA
VB .NET 2005

I want have a textbox formatted based on how many characters have been entered. It's for a project number.

Our project number system is:
0000-000-00

However, for search purposes the user is able to only enter a minimum of the first 4 characters such as D342.

If the user enters D342 that all I want shown - no dashes.

As soon as a user types a fifth character, I want the text in the textbox to now show:
D342-

The problem I'm having it that the cursor moves to the beginning of the text box after I add the dash. I could be using the wrong method for the textbox.
 
Eagle:

I've done similar things, but I always use one text box per letter, not allowing more than one, and the textboxes are formatted so that they are allowed only a number (in my case). I do this on the mouse events, enter events, and leave events.

This way, the user can NEVER enter more digits than is needed, and you simply concatenate the strings within the textboxes.

Here's a sample of how I did it for a phone number:

Code:
'AC=Area Code
'X=Extension
'P=Last 4 digits of phone

Private Sub PhoneTextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AC1.TextChanged, AC2.TextChanged, AC3.TextChanged, X1.TextChanged, X2.TextChanged, X3.TextChanged, P1.TextChanged, P2.TextChanged, P3.TextChanged, P4.TextChanged
        Select Case sender.name
            Case "AC1"
                AC2.Focus()
            Case "AC2"
                AC3.Focus()
            Case "AC3"
                X1.Focus()
            Case "X1"
                X2.Focus()
            Case "X2"
                X3.Focus()
            Case "X3"
                P1.Focus()
            Case "P1"
                P2.Focus()
            Case "P2"
                P3.Focus()
            Case "P3"
                P4.Focus()
            Case "P4"
                PC1.Focus()
        End Select

    End Sub 'PhoneTextChanged

    Private Sub PhoneEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles AC1.Enter, AC2.Enter, AC3.Enter, X1.Enter, X2.Enter, X3.Enter, P1.Enter, P2.Enter, P3.Enter, P4.Enter

        Select Case sender.name
            Case "AC1"
                AC1.SelectAll()
            Case "AC2"
                AC2.SelectAll()
            Case "AC3"
                AC3.SelectAll()
            Case "X1"
                X1.SelectAll()
            Case "X2"
                X2.SelectAll()
            Case "X3"
                X3.SelectAll()
            Case "P1"
                P1.SelectAll()
            Case "P2"
                P2.SelectAll()
            Case "P3"
                P3.SelectAll()
            Case "P4"
                P4.SelectAll()
        End Select
    End Sub 'PhoneEnter

    Private Sub PhoneMouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles AC1.MouseUp, AC2.MouseUp, AC3.MouseUp, X1.MouseUp, X2.MouseUp, X3.MouseUp, P1.MouseUp, P2.MouseUp, P3.MouseUp, P4.MouseUp
        Select Case sender.name
            Case "AC1"
                AC1.SelectAll()
            Case "AC2"
                AC2.SelectAll()
            Case "AC3"
                AC3.SelectAll()
            Case "X1"
                X1.SelectAll()
            Case "X2"
                X2.SelectAll()
            Case "X3"
                X3.SelectAll()
            Case "P1"
                P1.SelectAll()
            Case "P2"
                P2.SelectAll()
            Case "P3"
                P3.SelectAll()
            Case "P4"
                P4.SelectAll()
        End Select
    End Sub 'Phone_MouseUp

    Private Sub PhoneLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles AC1.Leave, AC2.Leave, AC3.Leave, X1.Leave, X2.Leave, X3.Leave, P1.Leave, P2.Leave, P3.Leave, P4.Leave
        If Len(sender.text) > 1 Then
            MessageBox.Show("You can only have 1 number in this box.", "Information Systems", MessageBoxButtons.OK, MessageBoxIcon.Information)
            sender.focus()
            sender.SelectAll()
        End If
    End Sub 'PhoneLeave

    Private Sub PhoneKeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles AC1.KeyUp, AC2.KeyUp, AC3.KeyUp, X1.KeyUp, X2.KeyUp, X3.KeyUp, P1.KeyUp, P2.KeyUp, P3.KeyUp, P4.KeyUp
        Select Case e.KeyCode
            Case Keys.Enter

                Select Case sender.name
                    Case "AC1"
                        AC2.Focus()
                    Case "AC2"
                        AC3.Focus()
                    Case "AC3"
                        X1.Focus()
                    Case "X1"
                        X2.Focus()
                    Case "X2"
                        X3.Focus()
                    Case "X3"
                        P1.Focus()
                    Case "P1"
                        P2.Focus()
                    Case "P2"
                        P3.Focus()
                    Case "P3"
                        P4.Focus()
                    Case "P4"
                        PC1.Focus()
                End Select
        End Select

    End Sub

'PC1 is the next text box after the phone number.

I also used labels to show the dashes in between the area code, extension, and 4 digit phone #.

I'm not sure if there is an equivalent to the masked edit box in VB.Net, but I'm sure one of the experts will steer you further (and probably better)

I hope this helps.

Ron Repp

If gray hair is a sign of wisdom, then I'm a genius.
 
I thought this was going to be easy!!

Getting the Dash to appear only when required WAS easy, getting the cursor in the "right" place was a nightmare.

This is not perfect, but unfortunately the SelectionStart and TextLength (or Text.Length) properties don't want to co-operate.

I said above, that getting the cursor in the right place was a nightmare and my solution only partially works in this respect. The cursor keys can be used to position the cursor anywhere and the next character will be typed at that point, however the cursor is then positioned to the end of the string. It may be possible to find a solution, but not at gone midnight. The problem appears to be in the way the control treats the Dash.

I've copied the MaskedTextBox properties that I used from the designer to save retyping them:
Code:
		'
		'MaskedTextBox1
		'
		Me.MaskedTextBox1.BeepOnError = True
		Me.MaskedTextBox1.Location = New System.Drawing.Point(74, 36)
		Me.MaskedTextBox1.Mask = "A"
		Me.MaskedTextBox1.Name = "MaskedTextBox1"
		Me.MaskedTextBox1.PromptChar = Global.Microsoft.VisualBasic.ChrW(32)
		Me.MaskedTextBox1.Size = New System.Drawing.Size(243, 20)
		Me.MaskedTextBox1.TabIndex = 0

The code that "sort of works"

Code:
	Private Sub MaskedTextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MaskedTextBox1.KeyPress

		e.KeyChar = Char.ToUpper(e.KeyChar)

	End Sub

	Private Sub MaskedTextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MaskedTextBox1.TextChanged

		SendKeys.Send("{END}{LEFT}")
		With MaskedTextBox1
			Dim l As Integer = .Text.Replace("-"c, "").Length
			Select Case l
				Case 0 To 4
					.Mask = "AAAAA".Substring(0, l + 1)
				Case 5 To 7
					.Mask = "AAAA-AAAA".Substring(0, l + 2)
				Case 8, 9
					.Mask = "AAAA-AAA-AA"
					If l = 9 Then SendKeys.Send("{END}")
			End Select
		End With

	End Sub


Hope this helps.

[vampire][bat]
 
This seems to solve it (amazing what a couple of hours sleep can do!):

Code:
	Private Sub MaskedTextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MaskedTextBox1.KeyPress

		e.KeyChar = Char.ToUpper(e.KeyChar)

	End Sub

	Private Sub MaskedTextBox1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MaskedTextBox1.KeyUp

		With MaskedTextBox1
			If e.KeyCode <> Keys.Left AndAlso .SelectionStart <> 0 AndAlso .SelectionStart < .TextLength Then
				If .Text.Substring(.SelectionStart - 1, 1) = "-" Then
					SendKeys.Send("{RIGHT}")
				End If
			End If
		End With

	End Sub

	Private Sub MaskedTextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MaskedTextBox1.TextChanged

		With MaskedTextBox1
			Dim l As Integer = .Text.Replace("-"c, "").Length
			Select Case l
				Case 0 To 4
					.Mask = "AAAAA".Substring(0, l + 1)
				Case 5 To 7
					.Mask = "AAAA-AAAA".Substring(0, l + 2)
				Case 8, 9
					.Mask = "AAAA-AAA-AA"
			End Select
		End With

	End Sub


Hope this helps.

[vampire][bat]
 
Because the Mask always allows space for the next character, pressing End will cause a problem with the above code so:

Code:
	Private Sub MaskedTextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MaskedTextBox1.KeyPress

		e.KeyChar = Char.ToUpper(e.KeyChar)

	End Sub

	Private Sub MaskedTextBox1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MaskedTextBox1.KeyUp

		With MaskedTextBox1
			If e.KeyCode = Keys.End AndAlso .SelectionStart <> 0 Then
				Try
					Dim s As String = .Text.Substring(.SelectionStart, 1)
				Catch ex As Exception
					SendKeys.Send("{LEFT}")
				End Try
			Else
				If e.KeyCode <> Keys.Left AndAlso .SelectionStart <> 0 AndAlso .SelectionStart < .TextLength Then
					If .Text.Substring(.SelectionStart - 1, 1) = "-" Then
						SendKeys.Send("{RIGHT}")
					End If
				End If
			End If
		End With

	End Sub

	Private Sub MaskedTextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MaskedTextBox1.TextChanged

		With MaskedTextBox1
			Dim l As Integer = .Text.Replace("-"c, "").Length
			Select Case l
				Case 0 To 4
					.Mask = "AAAAA".Substring(0, l + 1)
				Case 5 To 7
					.Mask = "AAAA-AAAA".Substring(0, l + 2)
				Case 8, 9
					.Mask = "AAAA-AAA-AA"
			End Select
		End With

	End Sub


Hope this helps.

[vampire][bat]
 
Replace:
Code:
    Private Sub MaskedTextBox1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MaskedTextBox1.KeyUp

        With MaskedTextBox1
            If e.KeyCode = Keys.End AndAlso .SelectionStart <> 0 Then
                Try
                    Dim s As String = .Text.Substring(.SelectionStart, 1)
                Catch ex As Exception
                    SendKeys.Send("{LEFT}")
                End Try
            Else
                If e.KeyCode <> Keys.Left AndAlso .SelectionStart <> 0 AndAlso .SelectionStart < .TextLength Then
                    If .Text.Substring(.SelectionStart - 1, 1) = "-" Then
                        SendKeys.Send("{RIGHT}")
                    End If
                End If
            End If
        End With

    End Sub


With:
Code:
	Private Sub MaskedTextBox1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MaskedTextBox1.KeyUp

		With MaskedTextBox1
			If e.KeyCode = Keys.End Then
				If Not .MaskFull Then SendKeys.Send("{LEFT}")
			Else
				If e.KeyCode <> Keys.Left AndAlso .SelectionStart <> 0 AndAlso .SelectionStart < .TextLength Then
					If .Text.Substring(.SelectionStart - 1, 1) = "-" Then
						SendKeys.Send("{RIGHT}")
					End If
				End If
			End If
		End With

	End Sub

which overcomes the problem when pressing End when the Mask is full, the previous version moved the cursor back one place.

Hope this helps.

[vampire][bat]
 
E & A:

Thanks for the info on the MaskedTextBox, however, in the original post, MaskedTextBox was not mentioned.
I want have a textbox formatted based on how many characters have been entered. It's for a project number.

So, please don't chastise me for trying to help.



Ron Repp

If gray hair is a sign of wisdom, then I'm a genius.
 
RonRepp, no chastisement was intended.

In your post you said:

RonRepp said:
I'm not sure if there is an equivalent to the masked edit box in VB.Net

and I was simply replying to that.

I'm aware that the original request was for a TextBox, but in view of the functionality pre-built into the MaskedTextBox (and that the first line of the original post indicated that VB 2005 was being used), it seemed far more sensible for me to work with that control. To achieve the same effect with a single TextBox would have required a phenominal amount of additional (and in reality - unnecessary) programming. As it is it took a fair bit of effort to properly handle cursor control - and I've spotted another problem: Pasted text longer than the "current" mask will only accept the available number of characters - I'll look into that if I get time.

In any event, since EagleTempest hasn't yet replied, we don't know which solution (if either) he chose to adopt.



[vampire][bat]
 
E & A:

That is exactly why I posted what I did. A text box is a text box is a text box. It hasn't changed a heckuva lot since VB5, and forgive me for assuming, but I figured it hadn't changed in 2005.

If you looked at my code, you would see the ease of formatting a group of TBs to make it appear as the programmer wanted by simply concatenating the string produced.

I used 5 events and minimal code to handle a custom format string any way imaginable. As for how it works, mine is pretty brain-dead code. That's because I'm brain dead, for the most part. You're a great programmer and have helped me countless times, and for that I thank you.

However, you are right, until ET gets back to the post, it's anybody's guess. He/she may have gone a completely different route, and if he did, I'd like to see that, too.

Thanks for all your help.

Ron Repp

If gray hair is a sign of wisdom, then I'm a genius.
 
Sorry guys. I had tried to post a reply days ago but something must have happened.

I had come up with my own code.
Code:
 Private Sub txt1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txt1.TextChanged
    Dim strclient, strJob, strSub As String
    If blnUpdated = True And txt1.TextLength > 0 Then
      blnUpdated = False

      'Check if last char in textbox is a dash
      If Mid(txt1.Text, txt1.TextLength, 1) = "-" Then
        txt1.Text = Mid(txt1.Text, 1, txt1.TextLength - 1)
      End If

      Select Case txt1.TextLength
        Case 5
          '1234 and keypressed.
          strclient = Mid(txt1.Text, 1, 4)
          strJob = Mid(txt1.Text, 5, 1)

          txt1.Text = strclient & "-" & strJob
        Case 6 To 8
          '1234-5 and keypressed  .
          strclient = Mid(txt1.Text, 1, 4)
          strJob = Mid(txt1.Text, 6, txt1.TextLength - 5)

          txt1.Text = strclient & "-" & strJob
        Case 9
          '1234-567- and keypressed.
          strclient = Mid(txt1.Text, 1, 4)
          strJob = Mid(txt1.Text, 5, 4)
          strSub = Mid(txt1.Text, 9, 1)

          txt1.Text = strclient & strJob & "-" & strSub
        Case 10
          '1234-567-8 and keypressed.
          strclient = Mid(txt1.Text, 1, 4)
          strJob = Mid(txt1.Text, 5, 4)
          strSub = Mid(txt1.Text, 9, 2)

          txt1.Text = strclient & strJob & strSub
        Case Is = 11
          '1234-567-89 and keypressed.
          txt1.Text = Mid(txt1.Text, 1, 11)
      End Select

      'Move cursor to end of text string.
      txt1.SelectionStart = txt1.TextLength
      txt1.SelectionLength = 0

      txt1.Tag = Replace(txt1.Text, "-", "")
      blnUpdated = True
    End If

  End Sub

But thanks for all your help. There's always for then one way to do something.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top