Post by Rod on Nov 30, 2022 14:37:40 GMT
This code takes control of textboxes and maps the user input against a mask that defines what characters are acceptable. It also applies a range check. A Lhun check digit check is included. This is the hash that most credit card and barcode numbers employ when the number is manually input. It simply verifies that the till operator has entered the number correctly.
nomainwin
WindowWidth = 500
WindowHeight = 400
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
'open a hidden graphicbox to capture keypresses when required
graphicbox #main.hidebox, 0, 0, 0, 0
statictext #main.stdate,"Date",20,23,50,20
textbox #main.tbdate,80,20,120,20
statictext #main.stdatem,"key dd mm yyyy the / is autofilled",220,23,200,20
statictext #main.stacct, "Account", 20, 53, 50, 20
textbox #main.tbacct, 80, 50, 120, 20
statictext #main.stdatem,"key ac no 1234567891234563 ",220,53,200,20
statictext #main.ststock, "Stock Ref", 20, 80, 50, 20
textbox #main.tbstock, 80, 80, 120, 20
statictext #main.stprice, "Price", 20, 110, 50, 20
textbox #main.tbprice, 80, 110, 120, 20
statictext #main.stvolume, "Volume", 20, 140, 50, 20
textbox #main.tbvolume, 80, 140, 120, 20
button #main.enter, "Enter",enter,UL, 80,170,40,20
button #main.abort, "Abort",abort,UL, 150,170,40,20
open "User Input" for window as #main
#main "trapclose quit"
#main.tbdate "!disable"
#main.tbacct "!disable"
#main.tbstock "!disable"
#main.tbprice "!disable"
#main.tbvolume "!disable"
#main.enter "!disable"
'we will just demonstrate the first two inputs
[date]
mask$="MM/DD/YYYY"
low$="01/01/1900"
high$="12/31/2020"
#main.tbdate mask$
#main.tbdate maskInput$("#main.tbdate",mask$,low$,high$)
[acct]
mask$="NNNNNNNNNNNNNNNC"
low$ ="0000000000000000"
high$="9999999999999999"
#main.tbacct mask$
#main.tbacct maskInput$("#main.tbacct",mask$,low$,high$)
'[stock]
'mask$="AAA-NNN-NNN"
'low$ ="----000-000"
'high$="----999-999"
'#main.tbstock mask$
'#main.tbstock maskInput$("#main.tbstock",mask$,low$,high$)
'[price]
'mask$="NNNN.NN"
'low$ ="0010.00"
'high$="9999-99"
'#main.tbprice mask$
'#main.tbprice maskInput$("#main.tbprice",mask$,low$,high$)
'[volume]
'mask$="NNNN"
'low$="0001"
'high$="9999"
'#main.tbvolume mask$
'#main.tbvolume maskInput$("#main.tbvolume",mask$,low$,high$)
'now the form is complete enable the enter key
#main.enter "!enable"
wait
sub enter h$
close #main
end
end sub
sub abort h$
close #main
end
end sub
sub quit h$
close #main
end
end sub
function maskInput$(hnd$,msk$,low$,hig$) 'returns string matching the mask or an empty string
'what is the first thing to be checking?
next$=left$(msk$,1)
'if numeric how long
if instr("DMYN",next$)>0 and numlen=0 then
startofnumber=pos+1
n$=next$
numlen=1
while n$=next$ or n$="C"
numlen=numlen+1
n$=mid$(msk$,pos+numlen,1)
wend
numlen=numlen-1
lengthofnumber=numlen
end if
'wait for a keypress from the hidden graphicbox
#main.hidebox "when characterInput [start]"
#main.hidebox "setfocus"
wait
'function returns string as per mask and range limits
'hnd$ is the handle of the calling textbox
'msk$ defines the character by character input
'DMYNC is numeric leading and trailing zeros required, no negative signing
'if you need negative values ie deductions use a dedicated textbox
'D=Day
'M=Month
'Y=Year
'N=Numeric
'C=Luhn check digit
'A is upper case alpha
'-/\.# are data separators and will be inserted in the string automatically
'to aid human readable printing
'low$ defines the minimum value for any numeric input
'hig$ defines the maximum value for any numeric input
[start]
'a key was pressed so turn of polling and handle it
#main.hidebox "when characterInput"
key$=Inkey$
if len(key$)=1 then
key=asc(key$)
else
if asc(left$(key$,1))<>0 then
key=asc(right$(key$,1))
else
key=0
end if
end if
'print "pos ";pos," NumLen ";numlen," ";i$
select case
'case key=27
' 'esc was pressed abort masked input
' goto [abort]
case key=8
'backspace was pressed delete last character
i$=left$(i$,pos-1)
pos=pos-1
numlen=numlen-(numlen>0)
scan
'if we hit a separator delete it also
if instr("-/\.#",mid$(msk$,pos+1,1)) then
i$=left$(i$,pos-1)
pos=pos-1
end if
case key>=48 and key<=57 or key >=65 and key <=90 or key >=97 and key <=122
'an alpha A-Z numeric 0-9 key was pressed
'a lowercase alpha is forced to upper
if key >=97 then key =key - 32
'if numeric
if instr("DMYNC",mid$(msk$,pos+1,1))>0 and key>=48 and key<=57 then
'if the mask is DMYNC and the key press is numeric accept it
i$=i$+chr$(key)
pos=pos+1
numlen=numlen-1
if numlen=0 then
'check range if we are at the end of the number input
v=val(mid$(i$,startofnumber,lengthofnumber))
if v>val(mid$(hig$,startofnumber,lengthofnumber))or v<val(mid$(low$,startofnumber,lengthofnumber))then
playwave "beep",async
i$=left$(i$,startofnumber-1)
pos=startofnumber-1
numlen=lengthofnumber
end if
'check lhun if last mask = C
if next$="C" and luhn(mid$(i$,startofnumber,lengthofnumber))<>1 then
playwave "beep",async
i$=left$(i$,startofnumber-1)
pos=startofnumber-1
numlen=lengthofnumber
end if
end if
end if
'if alpha
if mid$(msk$,pos+1,1)="A" and key>=65 and key<=90 then i$=i$+chr$(key) : pos=pos+1
end select
'what is next?
next$=mid$(msk$,pos+1,1)
'if it is a separator insert it
if instr("-/\.#",next$) then
i$=i$+next$
pos=pos+1
next$=mid$(msk$,pos+1,1)
end if
'print what we have and the rest of the mask
#hnd$ i$+right$(msk$,len(msk$)-len(i$))
'if numeric how long
if instr("DMYN",next$)>0 and numlen=0 then
startofnumber=pos+1
n$=next$
numlen=1
while n$=next$ or n$="C"
numlen=numlen+1
n$=mid$(msk$,pos+numlen,1)
wend
numlen=numlen-1
lengthofnumber=numlen
end if
'if complete finnish
if len(i$)=len(msk$) then goto [done]
'else start polling again
#main.hidebox "when characterInput [start]"
#main.hidebox "setfocus"
wait
'[abortinput]
'i$=""
[done]
#main.hidebox "when characterInput"
'#hnd$ "!enable"
#hnd$ i$
maskInput$=i$
end function
function luhn(num$) 'returns 1 if luhn check digit is correct 0 if not
cd$=right$(num$,1)
num$=left$(num$,len(num$)-1)
luhn=0
odd=0
sum = 0
for n = len(num$) to 1 step -1
num=val(mid$(num$,n,1))
if odd then
sum = sum + num
odd=0
else
num=num*2
if num<=9 then
sum = sum + num
else
sum = sum + val(left$(str$(num),1)) + val(right$(str$(num),1))
end if
odd=1
end if
next
if sum mod 10 > 0 then
ln$=str$(10-sum mod 10)
else
ln$="0"
end if
if cd$=ln$ then luhn=1
end function