TextBox Input Filter?

dlfallen

Active Member
Licensed User
Longtime User
Has anyone figured out a way to filter textbox input? For example, I wish to have the textbox ignore any key press that is not numeric. I tried the IsNumber function in the KeyPress event but that doesn't work.

The first approach I tried was:

Sub TextBox1_KeyPress (key)
if IsNumeric(key) = False then key = ""
End Sub

But changing the variable "key" within that subroutine does not do anything to what is displayed in the textbox. To illustrate this, replace the "if" statement above with "key = R". The textbox will still display what you type, not the value "R".

My second approach was to chop the right-hand character off of TextBox1.Text but alas, TextBox1.Text is not updated until AFTER the TextBox1.KeyPress(key) subroutine has been completed.

The only other events for a textbox are GotFocus and LostFocus, neither of which helps for this problem. The KeyPress event allows me to detect which key was pressed, but does not let me do anything about it.

Any ideas?

-dlfallen
 

Rioven

Active Member
Licensed User
Longtime User
Code help anyone...

B4PPC community, Hi!

I'm coding a dynamic textbox input and need help (the last item).
Any simple or correct solution for these filters?

B4X:
Sub HHStart_KeyPress (key) 

  'input only number
If IsNumber(key) = false AND Asc(key) <> 8  Then HHstart.IgnoreKey

  'mouse selected character and replace
If StrLength(HHStart.Text) <=2 AND HHstart.SelectionLength<>0 Then
s = HHStart.SelectionStart
HHstart.Text=StrRemove(HHstart.Text,s,HHstart.SelectionLength)
HHStart.SelectionStart=s
End If

  'limiting input length
If StrLength(HHstart.text)>=2 AND Asc(key) > 31 Then HHstart.IgnoreKey

  'limiting input number range
????????? from 0 to 24 only

End Sub

Thanks in advance:D
 

agraham

Expert
Licensed User
Longtime User
Could be a bit more elegant, especially if you removed the need to replace a selected character, but it works.
B4X:
Sub HHStart_KeyPress (key)

   'process only numbers, Asc("0")=48, AsSc("1")= 50 etc. and backspace = 8
   If (IsNumber(key) = false AND Asc(key) <> 8) Then
      HHstart.IgnoreKey
      Return
   End If

   If HHstart.SelectionLength <> 0 Then
      s = HHStart.SelectionStart
      If s = 0 AND Asc(key) > 50 AND  StrLength(HHStart.Text) >=2 Then 
         ' only allow first digit to be in range
         HHstart.IgnoreKey
         Return
      End If
      HHstart.Text=StrRemove(HHstart.Text,s,HHstart.SelectionLength)
      HHStart.SelectionStart=s
   End If

             'limit input number range 
     If StrLength(HHStart.Text) > 0 AND IsNumber(key) Then
      first = Asc(StrAt(HHStart.Text,0))
       If first > 50 Then
         HHstart.IgnoreKey ' first digit more than "2"
      Else If   first = 50 AND Asc(Key) > 52 Then
         HHstart.IgnoreKey ' final number would be > 24
      Else If StrLength(HHStart.Text) >= 2
         HHstart.IgnoreKey ' final number would be more then two digits
      End If      
   End If
End Sub
 

Rioven

Active Member
Licensed User
Longtime User
Hi agraham, thanks for your help, I could apply you techniques but still need to fix something...

when mouse is placed in between the 2 digits and use backspace, I could enter number that results more than 24, sometimes cannot enter any valid number.

or

When there is an existing 1 digit, and input number before this digit, I could enter number that results more than 24, sometimes cannot enter any valid number.

My problem looks simple, but seems no shortcut solution?:confused:

but if you can easily solve the above...will be much appreciated.

thanks again.
 

agraham

Expert
Licensed User
Longtime User
Maybe you can use a NumUpDown control instead of a TextBox?
Or maybe a TrackBar?

The logic is more complicated than it seems. So brute force then?

B4X:
Sub HHStart_KeyPress (key)
   'process only numbers and backspace
   If (IsNumber(key) = false AND Asc(key) <> 8) Then
      HHstart.IgnoreKey
      Return
   End If
End Sub

Sub HHStart_LostFocus (key)
   'process only numbers and backspace
   If HHStart.Text <0 OR HHStart.Text > 24 Then
      Msgbox("Must be between 0 and 24")
   HHStart.Focus
   End If
End Sub
 

Rioven

Active Member
Licensed User
Longtime User
Maybe you can use a NumUpDown control instead of a TextBox?

Yes Erel, I have thought about that and more often applied on hours, but if I have solution for these kind of filters on textbox, I could think of some other positive applications.


agraham said:
The logic is more complicated than it seems
:sign0148:difficult for years of not writing code like me, only started again when found Basic4PPC and still refreshing and learning. I could try to do some logic flowcharting then...as it seems I could not do it on the spot anymore.:D


thank you!
 

agraham

Expert
Licensed User
Longtime User
if I have solution for these kind of filters on textbox, I could think of some other positive applications.
I just love a challenge! Try to break this one


B4X:
Sub HHStart_KeyPress (key)
   ' I know this takes time but this is slow user input processing and avoids global clutter
   MAXNUM = 3456
   HHshadow = HHstart.text
   
   If (IsNumber(key) = false AND Asc(key) <> 8) Then
      'process only numbers, Asc("0")=48, AsSc("1")= 50 etc. and backspace = 8      
      HHstart.IgnoreKey
      Return
   Else If    HHstart.SelectionLength <> 0 Then
      ' part of string selected
      ss = HHStart.SelectionStart
      sl = HHStart.SelectionLength
      hl = StrLength(HHstart.text)
      first = SubString(HHshadow,0,ss)
      last = SubString(HHshadow,ss+sl,hl-sl)
      HHshadow = first & key & last      
   Else
      ' no selection so process normally and check limit
      HHshadow = HHshadow & key
   End If
   
   If IsNumber(key) AND  HHshadow > MAXNUM   Then
      HHstart.IgnoreKey
      Return   
   End If
End Sub
 

dzt

Active Member
Licensed User
agraham said:
I just love a challenge! Try to break this one

Easy!
;)

1. Type 0000 and at the beginning type any number
2. Paste anything Shift-Insert (desktop only, OK doesn't counts)
3. Type 555 and at the beginning try to type any number

:)
 

Rioven

Active Member
Licensed User
Longtime User
Easy!
;)

1. Type 0000 and at the beginning type any number
2. Paste anything Shift-Insert (desktop only, OK doesn't counts)
3. Type 555 and at the beginning try to type any number

:)

Not yet foolproof...
Add more logic operators...:eek:

@agraham, the challenge for this subroutine isn't over yet.:D
thanks for helping me...
EDIT:thanks for doing this... :sign0188:
 

Rioven

Active Member
Licensed User
Longtime User
This one seems working and applied as subroutine function....yet needs more improvements.:)

B4X:
Sub HHStart_KeyPress (key)
             'maxNum, ControlName,key
textboxFilter01("12345","HHStart",key)
End Sub

B4X:
Sub textboxFilter01(MaxNum,tb,key)
HHshadow=Control(tb).Text

'process only numbers and backspace
If (IsNumber(key) = false AND Asc(key) <> 8) Then
   Control(tb).ignorekey
   Return
End If

  'mouse selected character and replace
If Control(tb).SelectionLength<>0 AND Asc(key) <> 8 Then
s = Control(tb).SelectionStart
Control(tb).Text=StrRemove(Control(tb).Text,s,Control(tb).SelectionLength)
Control(tb).SelectionStart=s
n=StrInsert(Control(tb).Text,Control(tb).selectionstart,key)
      If (Asc(key) <> 8 AND n>maxNum ) Then 
      Control(tb).Text=HHshadow
      Control(tb).SelectionStart=s
      Control(tb).SelectionLength=1
      End If
End If

  'insert input
If StrLength(Control(tb).text)<StrLength(maxnum) Then
n=StrInsert(Control(tb).Text,Control(tb).selectionstart,key)
      If (Asc(key) <> 8 AND n>maxNum ) Then 
      Control(tb).ignoreKey
      End If
End If

  'limiting input length
If (StrLength(Control(tb).text)>=StrLength(maxnum) AND Asc(key) <> 8) Then
Control(tb).IgnoreKey
Return
End If
End Sub
feedbacks are welcome;)
 

agraham

Expert
Licensed User
Longtime User
Yeah. I realised that last night. There is a fundamental problem in that you don't know and can't find where the insertion point is. So you can deal with selections and normal input appended at the end but cannot predict the result of insertions. The only way round this I can think of is to reset the insertion point to disallow insertion and also disallow leading zeros

B4X:
Sub HHStart_KeyPress (key)
   ' I know this takes time but this is slow user input processing and avoids global clutter
   MAXNUM = 3456
   HHshadow = HHstart.text
   
   If  StrLength(HHstart.text) = 0 AND Asc(Key) = 48 Then
      'don't allow leading zeros
      HHstart.IgnoreKey
      Return
   End If
   
   If (IsNumber(key) = false AND Asc(key) <> 8) Then
      'process only numbers, Asc("0")=48, AsSc("1")= 50 etc. and backspace = 8      
      HHstart.IgnoreKey
      Return
   Else If    HHstart.SelectionLength <> 0 Then
      ' part of string selected
      ss = HHStart.SelectionStart
      sl = HHStart.SelectionLength
      hl = StrLength(HHstart.text)
      first = SubString(HHshadow,0,ss)
      last = SubString(HHshadow,ss+sl,hl-sl)
      HHshadow = first & key & last   
   Else
      ' no selection so process normally and check limit
      HHStart.SelectionStart = StrLength(HHshadow)
      HHshadow = HHshadow & key
   End If
   
   If IsNumber(key) AND  HHshadow > MAXNUM  Then
      HHstart.IgnoreKey
      Return   
   End If
End Sub
 

dzt

Active Member
Licensed User
Hello agraham,

I know it is very difficult and you do not have enough weapons to fight.

But if you use your ControlEvents and catch TextChanged event you need only to check for the value of the Textbox and if it is out of the limits, restore it to it's previous state or show a warning messagebox.

Didn't test it.

Am I wrong?
 

agraham

Expert
Licensed User
Longtime User
As dzt suggested here it is using my ControlEvents libary - a bit too easy really!
B4X:
Sub Globals
   'Declare the global variables here.
   MAXNUM = 3456
   Dim AGeventsTextSave

End Sub

Sub App_Start
             Form1.Show
             ' AGeventsX is a ControlEvents object
             AGeventsX.New1("AGevents")
End Sub

Sub AGeventsX_TextCHanged()
   If AGevents.Text > MAXNUM Then
       AGevents.Text = AGeventsTextSave
      AGevents.SelectionStart = StrLength(AGevents.text)
   Else
      AGeventsTextSave = AGevents.Text
   End If
End Sub
 
Top