Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Input routine
#1
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
Reply
#2
_inputbox$() see wiki
b = b + ...
Reply
#3
(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!)
Reply
#4
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.
Reply
#5
@SMcNeill what does this do?

Code: (Select All)
$If FALCON = TRUE Then
                QPrint p$
        $Else
            Print p$
        $End If
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#6
@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? Big Grin LOL!

You rock!
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#7
(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.  Wink


(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.)
Reply
#8
(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? Big Grin 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.  Wink

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.  Smile
Reply
#9
@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

grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#10
@SMcNeill will your input routing work in graphic modes?
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply




Users browsing this thread: 1 Guest(s)