Posts: 60
Threads: 11
Joined: Apr 2022
Reputation:
7
Does anyone know of a Windows-like input routine that has been written for QB64? Something that accepts mouse input, cut & paste, word wrap, etc.
I have looked through the forums and did not find anything.
Thanks in advance,
Dano
Posts: 3,982
Threads: 178
Joined: Apr 2022
Reputation:
220
_inputbox$() see wiki
b = b + ...
Posts: 60
Threads: 11
Joined: Apr 2022
Reputation:
7
(05-20-2024, 05:54 PM)bplus Wrote: _inputbox$() see wiki
You are 100% correct...although I should have made this clearer!
I am looking for something to replace QB64's Input statement that will also look like the rest of the QB64 program. I want my program to have the same look and feel throughout the entire operation. While the _inputbox$() would work, the look and feel is very different than the native QB64 program's look and feel.
I have a routine that I wrote years ago that gives some of this, but it is missing mouse support and a few other things so I started re-writing a new one a while back and then it dawned on me...let's not reinvent the wheel if someone already has this out there.
Thanks for the input! (LOL...get it...the INPUT...sheesh I better not quit my day job!)
Posts: 2,697
Threads: 328
Joined: Apr 2022
Reputation:
217
Code: (Select All)
ExtendedInput "{P}Enter your password =>", a$
Print
Print "Your password was =>"; a$
ExtendedInput "{PL08}Enter your password (max 8 digits) =>", a$
Print
Print "Your password was =>"; a$
ExtendedInput "{PL05UI}Enter your 5 digit numeric keycode =>", a$
Print
Print "Your keycode was =>"; a$
Print
Print "And without password hiding which makes the * characters:"
ExtendedInput "Enter your password =>", a$
Print
Print "Your password was =>"; a$
ExtendedInput "{L08}Enter your password (max 8 digits) =>", a$
Print
Print "Your password was =>"; a$
ExtendedInput "{L05UI}Enter your 5 digit numeric keycode =>", a$
Print
Print "Your keycode was =>"; a$
Print
Print "And now let's clean up after ourselves once we input something!"
ExtendedInput "{H}Enter your password =>", a$
Print
Print "Your password was =>"; a$
ExtendedInput "{HL08}Enter your password (max 8 digits) =>", a$
Print
Print "Your password was =>"; a$
ExtendedInput "{HL05UI}Enter your 5 digit numeric keycode =>", a$
Print
Print "Your keycode was =>"; a$
Sub ExtendedInput (prompt$, result$) 'Over Engineered Input
'limit VALUES:
'1 = Unsigned
'2 = Integer
'4 = Float
'8 = Who cares. It's handled via internal variables and we don't need to know a type for it.
'Uses {} at the start of the prompt to limit possible input
'P = Password
'U = Unsigned
'I = Integer
'F = Float
'L## = Length of max ##
'X##, Y## = LOCATE before printing
'D = Disable paste option
'V = Move CTRL-V to AFTER paste
'H = Hide Input after finished. (Won't leave prompt, or user input on the screen.)
PCopy 0, 1
A = _AutoDisplay: X = Pos(0): Y = CsrLin
OX = X: OY = Y 'original x and y positions
CP = 0: OldCP = 0 'Cursor Position
_KeyClear
length_limit = -1 'unlimited length input, by default
If Left$(prompt$, 1) = "{" Then 'possible limiter
i = InStr(prompt$, "}")
If i Then 'yep, we have something!
limiter$ = UCase$(Mid$(prompt$, 2, i - 2))
If InStr(limiter$, "U") Then limit = limit Or 1 'Unsigned
If InStr(limiter$, "I") Then 'can't limit to BOTH an integer AND a float
limit = limit Or 2 'Integer
ElseIf InStr(limiter$, "F") Then
limit = limit Or 4 'Float
float_before_limit = KB_GetValue(limiter$, "F")
float_after_limit = KB_GetValue(Mid$(limiter$, InStr(limiter$, "F") + 1), ".")
End If
End If
If InStr(limiter$, "P") Then password_protected = -1: limit = limit Or 8 'don't show passwords.
If InStr(limiter$, "L") Then 'Length Limitation
limit = limit Or 8
length_limit = KB_GetValue(limiter$, "L")
End If
If InStr(limiter$, "X") Then 'X position on screen
limit = limit Or 8
X = KB_GetValue(limiter$, "X")
End If
If InStr(limiter$, "Y") Then 'Y position on scren
limit = limit Or 8
Y = KB_GetValue(limiter$, "Y")
End If
If InStr(limiter$, "D") Then disable_paste = -1: limit = limit Or 8 'disable paste
If InStr(limiter$, "V") Then cursor_after_paste = -1: limit = limit Or 8 'disable paste
If InStr(limiter$, "H") Then clean_exit = -1: limit = limit Or 8 'hide after finished
End If
If limit <> 0 Then prompt$ = Mid$(prompt$, i + 1)
Do
PCopy 1, 0
If _KeyDown(100307) Or _KeyDown(100308) Then AltDown = -1 Else AltDown = 0
k = _KeyHit
If AltDown Then
Select Case k 'ignore all keypresses except ALT-number presses
Case -57 To -48: AltWasDown = -1: alt$ = alt$ + Chr$(-k)
End Select
Else
Select Case k 'without alt, add any keypresses to our input
Case 8
oldin$ = in$
If CP > 0 Then OldCP = CP: CP = CP - 1
in$ = Left$(in$, CP) + Mid$(in$, CP + 2) 'backspace to erase input
Case 9
oldin$ = in$
in$ = Left$(in$, CP) + Space$(4) + Mid$(in$, CP + 1) 'four spaces for any TAB entered
OldCP = CP
CP = CP + 4
Case 32 To 128
If _KeyDown(100305) Or _KeyDown(100306) Then
If k = 118 Or k = 86 Then
If disable_paste = 0 Then
oldin$ = in$
temp$ = _Clipboard$
in$ = Left$(in$, CP) + temp$ + Mid$(in$, CP + 1) 'ctrl-v paste
'CTRL-V leaves cursor in position before the paste, without moving it after.
'Feel free to modify that behavior here, if you want it to move to after the paste.
If cursor_after_paste Then CP = CP + Len(temp$)
End If
End If
If k = 122 Or k = 90 Then Swap in$, oldin$: Swap OldCP, CP 'ctrl-z undo
Else
check_input:
oldin$ = in$
If limit And 1 Then 'unsigned
If k = 43 Or k = 45 Then _Continue 'remove signs +/-
End If
If limit And 2 Then 'integer
If k = 45 And CP = 0 Then GoTo good_input 'only allow a - sign for the first digit
If k < 48 Or k > 57 Then _Continue 'remove anything non-numeric
End If
If limit And 4 Then 'float
If k = 45 And CP = 0 Then GoTo good_input 'only allow a - sign for the first digit
If k = 46 And InStr(in$, ".") = 0 Then GoTo good_input 'only one decimal point
If k < 48 Or k > 57 Then _Continue 'remove anything non-numeric
If Left$(in$, 1) = "-" Then temp$ = Mid$(in$, 2) Else temp$ = in$
If InStr(in$, ".") = 0 Or CP < InStr(in$, ".") Then
If Len(temp$) < float_before_limit Or float_before_limit = -1 Then
in$ = Left$(in$, CP) + Chr$(k) + Mid$(in$, CP + 1) 'add input to our string
OldCP = CP
CP = CP + 1
End If
Else
temp$ = Mid$(in$, InStr(in$, ".") + 1)
If Len(temp$) < float_after_limit Or float_after_limit = -1 Then
in$ = Left$(in$, CP) + Chr$(k) + Mid$(in$, CP + 1) 'add input to our string
OldCP = CP
CP = CP + 1
End If
End If
_Continue
End If
good_input:
If CP < length_limit Or length_limit < 0 Then
in$ = Left$(in$, CP) + Chr$(k) + Mid$(in$, CP + 1) 'add input to our string
OldCP = CP
CP = CP + 1
End If
End If
Case 18176 'Home
CP = 0
Case 20224 'End
CP = Len(in$)
Case 21248 'Delete
oldin$ = in$
in$ = Left$(in$, CP) + Mid$(in$, CP + 2)
Case 19200 'Left
CP = CP - 1
If CP < 0 Then CP = 0
Case 19712 'Right
CP = CP + 1
If CP > Len(in$) Then CP = Len(in$)
End Select
End If
alt$ = Right$(alt$, 3)
If AltWasDown = -1 And AltDown = 0 Then
v = Val(alt$)
If v >= 0 And v <= 255 Then
k = v
alt$ = "": AltWasDown = 0
GoTo check_input
End If
End If
blink = (blink + 1) Mod 30
Locate Y, X
p$ = prompt$
If password_protected Then
p$ = p$ + String$(Len(Left$(in$, CP)), "*")
If blink \ 15 Then p$ = p$ + " " Else p$ = p$ + "_"
p$ = p$ + String$(Len(Mid$(in$, CP + 1)), "*")
Else
p$ = p$ + Left$(in$, CP)
If blink \ 15 Then p$ = p$ + " " Else p$ = p$ + "_"
p$ = p$ + Mid$(in$, CP + 1)
End If
$If FALCON = TRUE Then
QPrint p$
$Else
Print p$
$End If
_Display
_Limit 30
Loop Until k = 13
PCopy 1, 0
Locate OY, OX
If clean_exit = 0 Then
Locate Y, X
If password_protected Then
p$ = prompt$ + String$(Len(in$), "*")
Else
p$ = prompt$ + in$
End If
$If FALCON = TRUE Then
QPrint p$
$Else
Print p$
$End If
End If
result$ = in$
If A Then _AutoDisplay
End Sub
Function KB_GetValue (limiter$, what$)
jstart = InStr(limiter$, what$): j = 0
If Mid$(limiter$, InStr(limiter$, what$) + 1, 1) = "-" Then
GetValue = -1 'unlimited
Exit Function
End If
Do
j = j + 1
m$ = Mid$(limiter$, jstart + j, 1)
Loop Until m$ < "0" Or m$ > "9"
KB_GetValue = Val(Mid$(limiter$, jstart + 1, j - 1))
End Function
Even without the limiter and prompt, this still gives you several word processing style extensions to the basic INPUT. For example, arrow keys work, as does the ability to use ALT+ASCII values to directly enter characters via their ascii code (such as ALT-1 for the little smiley face icon dude), as well as the ability to paste code into the input with CTRL-V.
Posts: 477
Threads: 25
Joined: Nov 2022
Reputation:
45
@SMcNeill what does this do?
Code: (Select All) $If FALCON = TRUE Then
QPrint p$
$Else
Print p$
$End If
Posts: 477
Threads: 25
Joined: Nov 2022
Reputation:
45
05-20-2024, 09:00 PM
(This post was last modified: 05-20-2024, 09:07 PM by grymmjack.)
@SMcNeill this is a great share! ExtendedInput! <3
Could you add cursor movement with Home, End, CTRL+arrows, and previous input history recall if supplied (up/down arrow), and insert mode? LOL!
You rock!
Posts: 2,697
Threads: 328
Joined: Apr 2022
Reputation:
217
05-20-2024, 09:35 PM
(This post was last modified: 05-20-2024, 09:49 PM by SMcNeill.)
(05-20-2024, 08:57 PM)grymmjack Wrote: @SMcNeill what does this do?
Code: (Select All) $If FALCON = TRUE Then
QPrint p$
$Else
Print p$
$End If
It's an old means of doing what _UPrintString does for us nowadays. Since there's no $LET FALCON = TRUE defined, it just does a basic PRINT command for us, where you tell it to.
(IF you're curious about QPRINT, see here: https://qb64phoenix.com/forum/showthread.php?tid=2251 -- this allows us to have word wrap, proper font displays, and other such features with our ExtendedInput.)
Posts: 2,697
Threads: 328
Joined: Apr 2022
Reputation:
217
(05-20-2024, 09:00 PM)grymmjack Wrote: @SMcNeill this is a great share! ExtendedInput! <3
Could you add cursor movement with Home, End, CTRL+arrows, and previous input history recall if supplied (up/down arrow), and insert mode? LOL!
You rock!
Doesn't it do all those already? Home goes to the start of your input. End to the end. Arrows keys left/right into the middle of the input.
Code: (Select All) Case 18176 'Home
CP = 0
Case 20224 'End
CP = Len(in$)
Case 21248 'Delete
oldin$ = in$
in$ = Left$(in$, CP) + Mid$(in$, CP + 2)
Case 19200 'Left
CP = CP - 1
If CP < 0 Then CP = 0
Case 19712 'Right
CP = CP + 1
If CP > Len(in$) Then CP = Len(in$)
CP is Cursor Position, so 0 is to the left of the text, LEN(in$) is the right of the text, and any value between those numbers is inside the input text.
There's no Insert mode (overwrite), but you're free to expand and alter what's here as you wish for your own personal needs.
Posts: 477
Threads: 25
Joined: Nov 2022
Reputation:
45
@SMcNeill I found my old IMPUT (IMProved inPUT) stuff. It's not as nice or easy to read as yours.
Sharing for fun here.
Code: (Select All)
OPTION _EXPLICIT
$Debug
_CONTROLCHR OFF
SCREEN 0
DIM AS STRING answer1, answer2, word1, word2, word3, words
DIM AS INTEGER row, col
DIM char_stats(4) AS INTEGER
PRINT "Choose a password 3-8 characters in length."
PRINT ": ";
answer1$ = imput$(3, 8, 0, "*", "_", "ENTER PASSWORD")
get_char_stats answer1$, char_stats%()
print_char_stats answer1$, char_stats%()
PRINT : PRINT "Enter a random thought..."
PRINT ": ";
answer2$ = imput$(0, 77, 1, "", ".", "it can literrally be anything...")
get_char_stats answer2$, char_stats%()
print_char_stats answer2$, char_stats%()
PRINT : PRINT "Now enter 3 different short words"
PRINT ": ";
row% = CSRLIN : col% = POS(0)
PRINT "____________________ ____________________ ____________________";
LOCATE row%, col%
word1$ = imput$(0, 20, 1, "", "_", "WORD 1")
LOCATE row%, col% + 21
word2$ = imput$(0, 20, 1, "", "_", "WORD 2")
LOCATE row%, col% + 42
word3$ = imput$(0, 20, 1, "", "_", "WORD 3")
words$ = word1$ + " " + word2$ + " " + word3$
get_char_stats words$, char_stats%()
print_char_stats words$, char_stats%()
''
' (imp)roved input draw string routine
' Draws from a position, then returns to that same position
' @param INTEGER row% row to draw on
' @param INTEGER col% col to start on
' @param STRING s$ string to draw
'
SUB imput_draw(row%, col%, s$)
LOCATE row%, col%, 1 : PRINT s$; : LOCATE row%, col%, 1
END SUB
''
' (imp)roved input
'
' - Accepts any visible characters (ASC(32)+)
' - Use ENTER to complete input
' - Can backspace, when backspace replaces with blank or empty_char$
' - +Can use delete, when pressing delete, removes from the right side
' - +Can use insert or overwrite mode
' - +Can use CTRL-LEFT and CTRL-RIGHT to move between words
' - +Can use HOME and END to go to home or end
' - +Can use TAB to insert spaces
' - +Configure to use sound or not (new param)
' - +Configure to use cursor or not (new param)
' - Abort with ESC (optional)
' - Clear with CTRL-K, CTRL-X, CTRL-Y
'
' @param INTEGER min% minimum length of input required
' @param INTEGER max% maximum length of input allowed
' @param INTEGER use_default% use placeholder as default value
' @param STRING echo_char$ instead of showing keys as typed use char$
' @param STRING empty_char$ to use instead of space
' @param STRING placeholder$ display string and as soon as key typed, clear it
' @return STRING of characters typed
'
FUNCTION imput$(min%, max%, use_default%, echo_char$, empty_char$, placeholder$)
DIM AS STRING k, ret
DIM AS INTEGER orig_row, orig_col, cur_row, cur_col, done
orig_row% = CSRLIN : orig_col% = POS(0)
cur_row% = orig_row% : cur_col% = orig_col%
IF empty_char$ = "" THEN empty_char$ = " "
IF max% > 0 THEN ' print max empty_char if placeholder blank
imput_draw orig_row%, orig_col%, STRING$(max%, empty_char$)
END IF
IF placeholder$ <> "" THEN ' print placeholder
imput_draw orig_row%, orig_col%, placeholder$
END IF
done% = 0
IF use_default% = 1 THEN
ret$ = placeholder$
LOCATE orig_row%, orig_col% + LEN(placeholder$), 1
END IF
DO:
_LIMIT 30
k$ = INKEY$
IF k$ <> "" THEN ' valid keypress
IF k$ = CHR$(27) THEN ' abort with ESCAPE
imput$ = "" : EXIT FUNCTION
END IF
IF k$ = CHR$(13) THEN ' finish with enter...
IF use_default% = 1 OR _
LEN(ret$) >= min% AND LEN(ret$) <= max% THEN ' and legal...
done% = 1
ELSE ' not legal because not long enough
BEEP
END IF
END IF
IF k$ = CHR$(24) _
OR k$ = CHR$(25) _
OR k$ = CHR$(11) THEN ' CTRL-(K,X,Y) = clear
IF LEN(ret$) > 0 THEN
ret$ = "" ' empty the contents of the user input
IF max% > 0 THEN ' if max, print empty_char$ * max
IF placeholder$ <> "" THEN
imput_draw orig_row%, orig_col%, STRING$(LEN(placeholder$), " ")
END IF
imput_draw orig_row%, orig_col%, STRING$(max%, empty_char$)
END IF
END IF
END IF
IF k$ = CHR$(8) THEN ' backspace
IF LEN(ret$) > 0 THEN 'something to erase exists
cur_row% = CSRLIN : cur_col% = POS(0)
imput_draw cur_row%, cur_col% - 1, empty_char$
ret$ = MID$(ret$, 1, LEN(ret$)-1)
END IF
IF LEN(ret$) = 0 THEN ' nothing to erase - print placeholder
IF max% > 0 THEN ' if max print empty_char$ * max
IF placeholder$ <> "" THEN
imput_draw orig_row%, orig_col%, STRING$(LEN(placeholder$), " ")
END IF
imput_draw orig_row%, orig_col%, STRING$(max%, empty_char$)
END IF
END IF
END IF
IF ASC(k$) >= 32 THEN ' valid printable character
IF LEN(ret$) + 1 <= max% THEN ' less than or equal to max
IF LEN(ret$) = 0 THEN ' clear placeholder on first key
IF placeholder$ <> "" THEN
imput_draw orig_row%, orig_col%, STRING$(LEN(placeholder$), empty_char$)
END IF
IF max% > 0 THEN ' if max print empty_char$ * max
IF placeholder$ <> "" THEN ' clear any placeholder
imput_draw orig_row%, orig_col%, STRING$(LEN(placeholder$), " ")
END IF
' draw empty chars length of max
imput_draw orig_row%, orig_col%, STRING$(max%, empty_char$)
END IF
END IF
ret$ = ret$ + k$ ' append user input
IF echo_char$ = "" THEN ' print echo_char or key itself
PRINT k$;
ELSE
PRINT echo_char$;
ENDIF
ELSE ' another char would exceed max so disallow
BEEP
END IF
END IF
END IF
LOOP UNTIL done% = 1
imput$ = ret$
END FUNCTION
''
' Returns statistics about a string
'
' @param STRING st$ string to get stats for
' @param INTEGER char_stats%() array to store stats in
'
SUB get_char_stats (st$, char_stats%())
IF st$ = "" THEN EXIT SUB
DIM AS INTEGER i, vowels, consonants, digits, symbols, spaces
DIM AS STRING ch, s
s$ = UCASE$(st$)
FOR i% = 1 TO LEN(st$)
ch$ = MID$(s$, i%, 1)
SELECT EVERYCASE ch$
CASE "A", "E", "I", "O", "U":
vowels% = vowels% + 1
CASE "B" TO "D", _
"F" TO "H", _
"J" TO "N", _
"P" TO "T", _
"V" TO "Z":
consonants% = consonants% + 1
CASE "0" TO "9":
digits% = digits% + 1
CASE CHR$(32), CHR$(13), CHR$(9):
spaces% = spaces% + 1
CASE ELSE:
symbols% = symbols% + 1
END SELECT
NEXT i%
char_stats%(0) = vowels%
char_stats%(1) = consonants%
char_stats%(2) = digits%
char_stats%(3) = symbols%
char_stats%(4) = spaces%
END SUB
''
' Print character stats for a string
' @param STRING st$ string to print stats for
' @param INTEGER char_stats%() array stats are in
'
SUB print_char_stats(st$, char_stats%())
IF st$ = "" THEN EXIT SUB
PRINT : PRINT
PRINT "String: "; st$
PRINT
PRINT "--- Statistics ---"
PRINT
PRINT "Length: "; _TRIM$(STR$(LEN(st$)))
PRINT
PRINT "Number of vowels: "; _TRIM$(STR$(char_stats%(0)))
PRINT "Number of consonants: "; _TRIM$(STR$(char_stats%(1)))
PRINT "Number of digits: "; _TRIM$(STR$(char_stats%(2)))
PRINT "Number of symbols: "; _TRIM$(STR$(char_stats%(3)))
PRINT "Number of spaces: "; _TRIM$(STR$(char_stats%(4)))
PRINT
END SUB
Posts: 477
Threads: 25
Joined: Nov 2022
Reputation:
45
@SMcNeill will your input routing work in graphic modes?
|