Formatting Numeric Input

Code snippets illustrating how LBB can be used
RNBW
Posts: 65
Joined: Thu Apr 05, 2018 9:21 pm

Re: Formatting Numeric Input

Post by RNBW »

Richard and Anatoly
Thanks for your comments. Won't be able to look further until Friday afternoon. If I don't manage that it'll be another week before my wife lets me get near a computer.

Ray
RNBW
Posts: 65
Joined: Thu Apr 05, 2018 9:21 pm

Re: Formatting Numeric Input

Post by RNBW »

I've had a quick look at the code and I was surprised to find that tsh73 is correct and chr$(77) could be used rather than chr$(8) and it wouldn't make any difference. In fact just about anything could be used, but you have to use something, so I'm happy with chr$(8): it does have some logic to it over other characters even if it doesn't make any difference what the character is.

Yes -.123 does need attention as does the editing of the number. I've never used EM_GETSEL so I'm not sure exactly how it is used. Could you give me an example please.

Going back to the chr$(8) issue and whether or not it actually reaches the text box, I'm still scratching my head about that. Maybe it'll come to me.
RNBW
Posts: 65
Joined: Thu Apr 05, 2018 9:21 pm

Re: Formatting Numeric Input

Post by RNBW »

The backspace character seems to be the cause of the problem with truncating the entered number if you subsequently edit it. As tsh73 says, almost any character has the same effect. chr$(77) is M, which doesn't seem to be the best to use, so I've plumped for chr$(0) which is NULL.

So the following code allows only input of characters 0-9, - and .
It also allows editing of the number entered.

Thank you to tsh73 for your help and to Richard for supporting him and showing where my code was wrong.

Corrected code:

Code: Select all

'==============================================
' Numeric entry into a textbox.
' This permits the entry of numbers including
' "-" and ".".  It also prevents more than one
' "-" and "." from being entered.
' Filename: NumericInputByChar_5
'----------------------------------------------
' Still to resolve: -.123 and zeros after 
' decimal point if it is the last character.
'==============================================

nomainwin
Stylebits #main.textbox, _ES_RIGHT, _WS_BORDER, 0, 0
textbox #main.textbox, 10, 50, 100, 25  
WindowWidth = 350  
WindowHeight = 150

open "Filtered Numeric Input" for window as #main  
#main.textbox "!contents? txt$"    
#main.textbox "!setfocus"
#main "trapclose [quit]"     

[CheckInput]       
timer 0
    
    #main.textbox "!contents? txt$"   'text in textbox
     oldtxt$ = txt$    ' make text the oldtext
    txt$ = num$(txt$)  ' gets new text from function num$(text$) which does the checking
    if oldtxt$ <> txt$ then
        #main.textbox txt$      ' if old text is not the same as the new text then use new text
        handle = hWnd(#main.textbox)   ' get the handle of the textbox
        pos = len(txt$)    ' position of character is the length of the current text
        calldll #user32, "SendMessageA", _   ' call EM_SETSEL
            handle as ulong, _
            _EM_SETSEL as long, _
            pos as long, _
            pos as long, _
            result as void
    end if

timer 500, [CheckInput]  ' TRY CHANGING TO timer 5000 TO SEE EFFECT OF REMOVING INVALID CHARACTERS
wait   ' wait for event

' Function to check that character input is 0-9, - or .
function num$(d$)
    t = 0
    for i=1 to len(d$)
        a=asc(mid$(d$,i,1))
        if a = 46 then t = t + 1
        if (a = 46) and (t > 1) then a = 0    'only DOT after FIRST is cleared
        if a = 45 and i>1 then a = 0          'so really almost anything do, not just 8
        if a = 46 and i = 1 then num$ = "0" + num$
        if a = 45 or a = 46 or a>47 and a<58 then num$=num$+chr$(a)
    next

end function

[quit]
close #main   ' close window
end                                                                            
If you want to see the effect of the removal of invalid characters more clearly edit the timer in the code to timer 5000.
RNBW
Posts: 65
Joined: Thu Apr 05, 2018 9:21 pm

Re: Formatting Numeric Input

Post by RNBW »

I've tried to resolve the display of -.123 to be -0.123 using the changes to the function num$(d$) as below, but it displays -00.123. How can this be resolved?

Code: Select all

function num$(d$)
    t = 0
    for i=1 to len(d$)
        a=asc(mid$(d$,i,1))
        if a = 46 then t = t + 1
        if (a = 46) and (t > 1) then a = 0    'only DOT after FIRST is cleared
        if a = 45 and i>1 then a = 0          'so really almost anything do, not just 8
        n$ = mid$(d$,i,2)
        if n$ = "-." then num$ = "-0" + num$
        if a = 46 and i = 1 then num$ = "0" + num$        
        if a = 45 or a = 46 or a>47 and a<58 then num$=num$+chr$(a)
    next
end function
RNBW
Posts: 65
Joined: Thu Apr 05, 2018 9:21 pm

Re: Formatting Numeric Input

Post by RNBW »

I've resolved the "-." issue and I've added a larger font to make the display clearer. Just the zero(s) after the decimal point if the last character is "."

Code: Select all

'==============================================
' Numeric entry into a textbox.
' This permits the entry of numbers including
' "-" and ".".  It also prevents more than one
' "-" and "." from being entered.
' Filename: NumericInputByChar_6
'----------------------------------------------
' Still to resolve: zeros after decimal
' point if it is the last character.
'==============================================

nomainwin
Stylebits #main.textbox, _ES_RIGHT, _WS_BORDER, 0, 0
textbox #main.textbox, 10, 50, 100, 25  
WindowWidth = 350  
WindowHeight = 150

open "Filtered Numeric Input" for window as #main  
print #main, "Font Arial 12 Bold"
#main.textbox "!contents? txt$"    
#main.textbox "!setfocus"
#main "trapclose [quit]"     

[CheckInput]       
timer 0
    
    #main.textbox "!contents? txt$"   'text in textbox
     oldtxt$ = txt$    ' make text the oldtext
    txt$ = num$(txt$)  ' gets new text from function num$(text$) which does the checking
    if oldtxt$ <> txt$ then
        #main.textbox txt$      ' if old text is not the same as the new text then use new text
        handle = hWnd(#main.textbox)   ' get the handle of the textbox
        pos = len(txt$)    ' position of character is the length of the current text
        calldll #user32, "SendMessageA", _   ' call EM_SETSEL
            handle as ulong, _
            _EM_SETSEL as long, _
            pos as long, _
            pos as long, _
            result as void
    end if

timer 500, [CheckInput]  ' short delay then last char is deleted if not 0-9, - or .
wait   ' wait for event

' Function to check that character input is 0-9, - or .
function num$(d$)
    t = 0
    for i=1 to len(d$)
        a=asc(mid$(d$,i,1))
        if a = 46 then t = t + 1
        if (a = 46) and (t > 1) then a = 0    'only DOT after FIRST is cleared
        if a = 45 and i>1 then a = 0          'so really almost anything do, not just 8
        if a = 46 and i = 1 then num$ = "0" + num$
        if a = 45 or a = 46 or a>47 and a<58 then num$=num$+chr$(a)
    next
    a=asc(mid$(num$,1,1))
    if a = 45 and mid$(num$,2,1) = "." then num$ = "-0" + num$

end function

[quit]
close #main   ' close window
end                                                                                       
alincon2001
Posts: 4
Joined: Mon Apr 16, 2018 1:51 am

Re: Formatting Numeric Input

Post by alincon2001 »

Does the numeric stylebits command not meet anyone's needs to prevent non-numeric input?

Stylebits #textboxname, _ES_NUMBER, 0, 0, 0

r.m.
RNBW
Posts: 65
Joined: Thu Apr 05, 2018 9:21 pm

Re: Formatting Numeric Input

Post by RNBW »

@Alincon
No. _ES_NUMBER only allows the entry of characters 0 to 9. It does not permit minus or a decimal point.

However, if all you want to enter is characters 0 to 9 then it is fine and obviously saves a lot of code.
tsh73
Posts: 44
Joined: Fri Apr 06, 2018 7:58 pm

Re: Formatting Numeric Input

Post by tsh73 »

Just to say, it does about everything I would ask.

Here I rewrote it without using ASCII codes
(same number of lines really, but now I see "-" and "." in code ;) )
(Oh. And it uses GOTO as CONTINUE statement ;) )

Code: Select all

function num$(d$)
    t = 0
    for i=1 to len(d$)
        a$=mid$(d$,i,1)
        if a$="." then t = t + 1
        if (a$=".") and (t > 1) then [skipChar]    'only DOT after FIRST is cleared
        if (a$="-") and (i>1) then [skipChar]
        if instr("-.0123456789", a$) then num$=num$+a$
[skipChar]
    next
    if left$(num$, 1) = "." then num$ = "0" + num$
    if left$(num$, 2)= "-." then num$ = "-0" + mid$(num$,2)
end function

RNBW
Posts: 65
Joined: Thu Apr 05, 2018 9:21 pm

Re: Formatting Numeric Input

Post by RNBW »

tsh73
Thank you for your help with the modification of the code to make it work. I must say it's a nice bit of code now and having seen the lines and lines of code elsewhere to produce the same or equivalent, it is very concise and saves a lot of error checking. All that it doesn't do is deal with a number ending with a decimal point. Numbers never end with a decimal point. 123. would always be written as 123.0 or 123.00, etc. I think it is better to either write this in yourself or apply formatting to the final number to add the zero(s).

And then there is your alternative code, which looks as though it will work equally as well, but contains the dreaded GOTOs.

Personally, I don't have a problem with GOTOs, in moderation. They can provide a quick and clear way of jumping to where you want in the code. The problem is overuse resulting in chaotic code. I remember many years ago (about 1980 and on an Amstrad CPC computer), I wrote a program to analyze beams and calculate steelwork sections. It worked a treat, but in those days memory was tight, so comments were minimal. Some years later, I came back to it to convert it for the PC using both QB64 and BBC Basic. It was a nightmare! I just couldn't follow some parts of it, there were so many GOTOs that jumped all over the program. I had to re-write from scratch in a structured fashion.
RNBW
Posts: 65
Joined: Thu Apr 05, 2018 9:21 pm

Re: Formatting Numeric Input

Post by RNBW »

We seem to have sorted out how to input numeric values into a single textbox with a validity check on each character as it is entered. So my next step is to enable this in a grid of textboxes. I had previously a solution that partially worked (it did not include entering a "0" before a decimal point at the beginning of a number and it truncated the number if you entered a second decimal point).

I used the code for the single textbox solution and it works with the exception of putting a "0" before the decimal point when it appears in a positive or negative number when the decimal point is at the beginning of the number. That statement is not quite correct. If you enter ".123" or "-.123", initially nothing happens. If you go back and edit the numbers by entering two invalid characters in the ".123" number and three invalid characters in the "-.123" number they change to the required "0.123" and "-0.123".

I can't see why it doesn't work in the first place nor why it does work with the adding of invalid characters.

Help please! The code is below:

Code: Select all

'===============================================
' FILENAME: NumericInputInAGrid_08.bas 
'===============================================

NoMainWin        
    Row = 3: Col =4
    Dim TB$(Row, Col)
    WindowWidth = 500
    WindowHeight = 200
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)

    bWidth = 100: bHt = 30  'width & height of textboxes

    'Sets up the grid of Textboxes
    TextboxColor$ = "white"
    print: print
    For i = 1 to Row
       For j = 1 to Col  
           Stylebits #main.tb, _ES_RIGHT, _WS_BORDER, 0, 0
           TextBox #main.tb, (bWidth)*j -100+20, (bHt)*i - 15, bWidth+1, bHt+1
           TB$(i,j) = "#main.tb"; "_r";i;"c";j           
           'print TB$(i,j)   ' prints out handles on main win if you REM nomainwin
           maphandle #main.tb, TB$(i,j)
       Next
    Next

    Open "untitled" For Window As #main
    #main, "Font Arial 11"
    #main "TrapClose Quit"

While Hwnd(#main)
    Scan
    For i = 1 To Row
       For j = 1 to Col                    
         Call checkInput TB$(i,j)         
       Next j 
    Next i
    CallDLL #kernel32, "Sleep", 300   As long, _
                                ret As void
    
Wend

'---------------------------------------------------------------
' Check the characters entered.
'---------------------------------------------------------------
Sub checkInput controlName$
    #controlName$ "!contents? txt$"
    initLen = Len(txt$)
    txt$ = num$(txt$)
    If Len(txt$) < initLen Then
        #controlName$ txt$
        handle = Hwnd(#controlName$)
        pos = Len(txt$)
        CallDLL #user32, "SendMessageA", handle As long, _
                                         _EM_SETSEL As long, _
                                         pos        As long, _
                                         pos        As long, _
                                         result     As void
    End If
End Sub

'------------------------
' Close down the program
'------------------------
Sub Quit handle$
    Close #handle$
    End
End Sub

'Valid number check
'-------------------------------------------------------------
function num$(d$)
    t = 0
    for x=1 to len(d$)
        a=asc(mid$(d$,x,1))
        if a = 46 then t = t + 1
        if (a = 46) and (t > 1) then a = 0
        if a = 45 and x>1 then a = 0
        if a = 46 and x = 1 then num$ = "0" + num$
        'if a = 45 and mid$(num$,2,1) = "." then num$ = "-0" + num$
        if a = 45 or a = 46 or a>47 and a<58 then num$=num$+chr$(a)
        ' chr$(46) = "." 
    next
    a=asc(mid$(num$,1,1))
    if a = 45 and mid$(num$,2,1) = "." then num$ = "-0" + num$
    
end function