Author Topic: Multi-Input Popup Box  (Read 5471 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Multi-Input Popup Box
« on: June 17, 2021, 04:35:46 pm »
(I'd posted this elsewhere, but thought I'd share it here so folks who might not be reading the other topic could locate this and maybe someday reference it, or make use of it, for their own stuff.)

Here's a little something which I tossed together in about 20 minutes this afternoon, which you might be able to use:

Code: QB64: [Select]
  1. Screen _NewImage(1280, 720, 32)
  2. Dim As String prompt(3), results(3)
  3. prompt(0) = "Name": prompt(1) = "Age": prompt(2) = "Sex": prompt(3) = "Phone Number"
  4. For i = 1 To 100 'Draw some stuff on the screen for a background
  5.     Line (Rnd * 1280, Rnd * 720)-(Rnd * 1280, Rnd * 720), _RGB32(Rnd * 255, Rnd * 255, Rnd * 255), BF
  6. Print "SLEEPING SO YOU CAN SEE OUR BACKGROUND"
  7. MultiInput 100, 100, prompt(), results(), 20
  8. Print: Print "As you can see, when finished, our pop up restored our background..."
  9. Print "And your answers were the following:"
  10. For i = 0 To UBound(results): Print results(i): Next
  11. Sub MultiInput (xPos, yPos, prompt() As String, results() As String, maxLength As Integer)
  12.     backupImage = _CopyImage(0) 'copy our screen
  13.     B = _Blend: _DontBlend: A = _AutoDisplay: u = UBound(prompt)
  14.     For i = 0 To u 'get box size
  15.         p = _PrintWidth(prompt(i)): If p > maxWidth Then maxWidth = p
  16.     Next
  17.     boxWidth = maxWidth + maxLength * _FontWidth + 10: boxheight = (u + 1) * (_FontHeight + 3)
  18.     Do
  19.         If Timer > t# + .5 Then blink = Not blink: t# = Timer
  20.         k = _KeyHit 'get input
  21.         Select Case k
  22.             Case 18432: selection = selection - 1: If selection < 0 Then selection = u 'up
  23.             Case 20480, 13: selection = selection + 1: If selection > u Then selection = 0 'down
  24.             Case 27: Exit Do 'esc is the exit/finish code
  25.             Case 8: results(selection) = Left$(results(selection), Len(results(selection)) - 1) 'backspace
  26.             Case 32 TO 255: results(selection) = results(selection) + Chr$(k) 'all else
  27.         End Select
  28.  
  29.         _PutImage , backupImage 'restore background
  30.         Line (xPos, yPos)-Step(boxWidth, boxheight), 0, BF: Line (x + xPos + maxWidth + 1, y + yPos)-Step(0, boxheight), -1 'draw box
  31.         For i = 0 To u
  32.             Line (x + xPos, y + i * (_FontHeight + 3) + yPos)-Step(boxWidth, _FontHeight + 3), -1, B
  33.             _PrintString (x + xPos + 2, y + i * (_FontHeight + 3) + yPos + 2), prompt(i)
  34.             If i = selection And blink Then out$ = results(i) + Chr$(219) Else out$ = results(i)
  35.             _PrintString (x + xPos + maxWidth + 3, y + i * (_FontHeight + 3) + yPos + 2), out$
  36.         Next
  37.         _Limit 30: _Display
  38.     Loop
  39.     _PutImage , backupImage
  40.     If B Then _Blend
  41.     _FreeImage backupImage

45 lines total, and  only 33 lines for our SUB, which does all the real work for us.

And what's this do, you ask?

It creates a simple, stand-alone, multi-line, POP-UP input box which we can use the arrow keys to move up and down between. 

Usage is rather simple:
1) Dim 2 arrays to hold your prompts and the results.
2) Set your prompts.
3) Call the function, get the results.

Can't be much simpler than that!
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Multi-Input Popup Box
« Reply #1 on: June 17, 2021, 06:12:42 pm »
That's handy.  You know, I didn't realize until looking through this code that you can do _COPYIMAGE(0) to grab the current screen.  I've always done it _COPYIMAGE(_DISPLAY). 

- Dav   

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Multi-Input Popup Box
« Reply #2 on: June 19, 2021, 06:59:40 am »
I like how this functions, it's also taught me a couple concepts I can utilize on my projects since I seem to end up doing a lot of dialog box input stuff. Up to this point, I haven't become familiar with _BLEND/_DONTBLEND and as Dav mentioned, I'm just discovering _COPYIMAGE(0)

I notice that 'x' and 'y' in lines 32-37 seem to be superfluous, I couldn't see where they were set, and cutting them out didn't affect the functioning of the code. I assume they are a "development artifact".

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Multi-Input Popup Box
« Reply #3 on: June 19, 2021, 08:49:06 am »
I like how this functions, it's also taught me a couple concepts I can utilize on my projects since I seem to end up doing a lot of dialog box input stuff. Up to this point, I haven't become familiar with _BLEND/_DONTBLEND and as Dav mentioned, I'm just discovering _COPYIMAGE(0)

I notice that 'x' and 'y' in lines 32-37 seem to be superfluous, I couldn't see where they were set, and cutting them out didn't affect the functioning of the code. I assume they are a "development artifact".

They are, here…. 

Originally, they were intended to be offsets to shared variables which might be used if you want to make the pop-up a subset of a different window.

Say I want to draw a large square box from 100,100 to 600,600.  Now imagine putting an image in the top 400 pixels of it…. And now you want to put in a quick input box with 3 or 4 choices below that and indented 50 pixels…. (Like for a visual novel style app.)

You’d need to do the math manually…. Left is 100 pixels + 50 indent.  Top is 100 pixels + 400 for image + 5 offset…. We’d call the pop-up at 150, 505….

OR….

We use those shared X/Y coordinates to represent top/left of the subframe, and then call it at 50,405.  (Or 50, 5, if we updated the shared y variable when we placed the image.)

I *was* going to demo the whole “frame a part of a frame” concept, but then thought it was a little beyond the scope of the original question, and I didn’t want to over complicate things.  (I have a bad tendency to over engineer my stuff sometimes, if you’ve ever noticed…)

You’ve got good eyes to spot those unnecessary artifacts though!  Since x/y isn’t shared here, they’re always 0, so they never actually do, or change, anything at all.  (Not to say that you couldn’t make them do something, if you wanted…)

I’m surpised you noticed them at all!  Seems you’ve studied my code even more than I have!  /blush!   I’ve got to check my stuff/edits better, in the future. 
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Multi-Input Popup Box
« Reply #4 on: June 19, 2021, 08:57:16 am »
As for why I’m making use of _DONTBLEND here:

Imagine having a background with a faded alpha image on it, and you want your pop-up to appear on it…  If you just draw a 255 alpha, 255 red box on a 128 alpha, 128 white screen, you’ll blend those colors together to make a 255 alpha, 128 red box.

Instead of putting a bright red box on the screen, you now have a faded pink box on it!

With _DONTBLEND, you don’t blend the red and white to make pink — you just replace the white completely with your red.

It’s used here, in this code, to make certain we draw our intended box ON TOP of whatever the screen had, rather than blending it into whatever exists there.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Multi-Input Popup Box
« Reply #5 on: June 19, 2021, 06:09:00 pm »
You’ve got good eyes to spot those unnecessary artifacts though!  Since x/y isn’t shared here, they’re always 0, so they never actually do, or change, anything at all.  (Not to say that you couldn’t make them do something, if you wanted…)

I’m surpised you noticed them at all!  Seems you’ve studied my code even more than I have!  /blush!   I’ve got to check my stuff/edits better, in the future.

I am intrigued by the approach, which looks really versatile for some of the things I do. In particular, I'm considering a rewrite of my grain truckload database, in which something like it would make a good input routine to layer over a background.

I pay pretty close attention to the subs and functions you've been doing, since your MBS routine has worked so well for most of my basic mouse ops that it's become my "GOTO" function.

I've also been on an optimization kick lately, where I've scrutinized a lot of my old code, finding heaps of stuff that I could throw away. Much of that based upon your advice on the subject. I guess I'm just getting the feel for it.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Multi-Input Popup Box
« Reply #6 on: June 19, 2021, 06:22:39 pm »
Hi guys and gals
Hi Steve
what can I say after seeing your new present to community toolbox? Just this: COOL!

Using it I must tell its neo:
on my screen number covers the vertical line at beginning of the field of input of number phone.
see attachment here
 
Number phone covers line of inputbox.JPG


and what to wish to say: are colors of output costumizable? Or does ti work only for white and black colors?
Thanks to share it Steve
Programming isn't difficult, only it's  consuming time and coffee

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Multi-Input Popup Box
« Reply #7 on: June 19, 2021, 07:17:59 pm »
Right now, to keep it simple, it’s only black and white, but you can change that easily.

Line (xPos, yPos)-Step(boxWidth, boxheight), 0, BF: Line (x + xPos + maxWidth + 1, y + yPos)-Step(0, boxheight), -1 'draw box

That one simple line statement is what draws our black background.  (Color 0 black background, color -1 white frame.) Change it, or make it variables to pass via parameter or shared values, and you can have any color background you want.  Changing the font color is just as simple as using a COLOR fg, bg statement at the top of the routine.  (Just be certain to change it back when the routine’s over.)

As for that last set of numbers overwriting the line….   I’m not certain why it’s doing that, off the top of my head.  I’ll have to dig into it a little more this evening and get back to you on it.  It might just need a slightly larger offset to shift it a pixel or two to the right, as QB64’s default font rendering can be slightly lacking sometimes.  (Like all the cases where parts of the font aren’t rendered at all, cutting them off completely, for instance…)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Multi-Input Popup Box
« Reply #8 on: June 19, 2021, 07:38:43 pm »
on my screen number covers the vertical line at beginning of the field of input of number phone.

The quick and dirty fix:

Change:
p = _PRINTWIDTH(prompt(i))

To:
p = _PRINTWIDTH(prompt(i)) + 1

It fixes the blanked line and doesn't impinge on the data fields too much.

P.S. It does display a tendency to echo the SLEEP keypress in the first field. Adding a _KEYCLEAR as the first statement of the SUB seems to fix that.
« Last Edit: June 19, 2021, 07:43:59 pm by OldMoses »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Multi-Input Popup Box
« Reply #9 on: June 19, 2021, 08:02:17 pm »
You guys have much better eyes than I do.  LOL!  I'd never spot these little 1-2 pixel issues. :P

The fixed code is here:

Code: QB64: [Select]
  1. Screen _NewImage(1280, 720, 32)
  2. Dim As String prompt(3), results(3)
  3. prompt(0) = "Name": prompt(1) = "Age": prompt(2) = "Sex": prompt(3) = "Phone Number"
  4. For i = 1 To 100 'Draw some stuff on the screen for a background
  5.     Line (Rnd * 1280, Rnd * 720)-(Rnd * 1280, Rnd * 720), _RGB32(Rnd * 255, Rnd * 255, Rnd * 255), BF
  6. Print "SLEEPING SO YOU CAN SEE OUR BACKGROUND"
  7. MultiInput 100, 100, prompt(), results(), 20
  8. Print: Print "As you can see, when finished, our pop up restored our background..."
  9. Print "And your answers were the following:"
  10. For i = 0 To UBound(results): Print results(i): Next
  11. Sub MultiInput (xPos, yPos, prompt() As String, results() As String, maxLength As Integer)
  12.     backupImage = _CopyImage(0) 'copy our screen
  13.     B = _Blend: _DontBlend: A = _AutoDisplay: u = UBound(prompt)
  14.     For i = 0 To u 'get box size
  15.         p = _PrintWidth(prompt(i)): If p > maxWidth Then maxWidth = p
  16.     Next
  17.     boxWidth = maxWidth + maxLength * _FontWidth + 10: boxheight = (u + 1) * (_FontHeight + 3)
  18.     Do
  19.         If Timer > t# + .5 Then blink = Not blink: t# = Timer
  20.         k = _KeyHit 'get input
  21.         Select Case k
  22.             Case 18432: selection = selection - 1: If selection < 0 Then selection = u 'up
  23.             Case 20480, 13: selection = selection + 1: If selection > u Then selection = 0 'down
  24.             Case 27: Exit Do 'esc is the exit/finish code
  25.             Case 8: results(selection) = Left$(results(selection), Len(results(selection)) - 1) 'backspace
  26.             Case 32 TO 255: results(selection) = results(selection) + Chr$(k) 'all else
  27.         End Select
  28.  
  29.         _PutImage , backupImage 'restore background
  30.         Line (xPos, yPos)-Step(boxWidth, boxheight), 0, BF
  31.         Line (xPos + maxWidth + 3, y + yPos)-Step(0, boxheight), -1 'draw box
  32.         For i = 0 To u
  33.             Line (xPos, y + i * (_FontHeight + 3) + yPos)-Step(boxWidth, _FontHeight + 3), -1, B
  34.             _PrintString (xPos + 2, y + i * (_FontHeight + 3) + yPos + 2), prompt(i)
  35.             If i = selection And blink Then out$ = results(i) + Chr$(219) Else out$ = results(i)
  36.             _PrintString (xPos + maxWidth + 6, y + i * (_FontHeight + 3) + yPos + 2), out$
  37.         Next
  38.         _Limit 30: _Display
  39.     Loop
  40.     _PutImage , backupImage
  41.     If B Then _Blend
  42.     _FreeImage backupImage
  43.  

The solution, in this case, is just programmer error.  When I calculated the length of my prompt's text, the longest line is stored as maxWidth.  I then build a box with a border 1 pixel thick, and shift my text right 2 pixels so I don't print over it with my prompts.  (_PrintString (xPos + 2... )

The problem comes where I didn't increase my offset everywhere else to account for that shift to the right, which causes the overlap and the misplacement.

Try the above and see if it doesn't correct the issue and align everything prettier for us.

A breakdown by pixels, for alignment, for width:

1 pixel for line frame.
1 pixel for back space.
boxWidth for longest prompt printed in box.
1 pixel for black space.
1 pixel for center divider line.
1 pixel for black space.
start of user input (max length determined by parameter)
space
line frame

Looking at the above, you can easily see where forgetting part of those offsets would shift stuff a few pixels out of place.
« Last Edit: June 19, 2021, 08:12:19 pm by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Multi-Input Popup Box
« Reply #10 on: June 19, 2021, 08:15:07 pm »
Seems to work perfectly now.

I have to study that blinking bit. I once tried something along a similar idea with TIMER, but it failed miserably.

As I recall, it was something like doing TIMER MOD 2 and checking for a zero value, but I was forgetting that TIMER doesn't yield an integer and wouldn't necessarily be caught by a loop.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Multi-Input Popup Box
« Reply #11 on: June 19, 2021, 08:17:53 pm »
P.S. It does display a tendency to echo the SLEEP keypress in the first field. Adding a _KEYCLEAR as the first statement of the SUB seems to fix that.

Honestly, I think a _KEYCLEAR should follow every SLEEP statement.  It’s just when we’re in a rush to churn out something real fast that we forget about it. 

Sleep: _KeyClear would probably be a better habit to get into than to stick on inside the sub itself.  You’ll never know when that some stray buffer stroke might come back to bite you somewhere else.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Multi-Input Popup Box
« Reply #12 on: June 19, 2021, 08:31:42 pm »
Seems to work perfectly now.

I have to study that blinking bit. I once tried something along a similar idea with TIMER, but it failed miserably.

As I recall, it was something like doing TIMER MOD 2 and checking for a zero value, but I was forgetting that TIMER doesn't yield an integer and wouldn't necessarily be caught by a loop.

Don’t study it *too* close, as it’s fundamentally flawed — it doesn’t account for time rolling over to 0 at midnight.  (Normally I use ExtendedTimer and not Timer for all my own stuff, so I never have to deal with that issue — it tracks time based off both date and time, rather than just time alone.)

The concept here though is very simple:

Blink is an on/off variable that determines if we show the cursor at the end, or not.
t# is the variable which stores the time.
TIMER + 0.5 > t# — this says if a half second has passed since we got the time last.

Which ends up with:

        If Timer > t# + .5 Then blink = Not blink: t# = Timer

Broken down, that’s:

If Timer > t# + .5 Then — IF 0.5 SECONDS HAVE PASSED
blink = Not blink — TOGGLE THE CURSOR ON/OFF
t# = Timer — RESET THE TIMER

It doesn’t get much simpler than that.  ;)



A quick fix for the midnight glitch would be a quick check:
IF TIMER < t# THEN t# = 0

(If the current timer is less than the old timer, then midnight has passed.)

Link to ExtendedTimer, as well: https://www.qb64.org/forum/index.php?topic=1598.0
« Last Edit: June 19, 2021, 08:37:21 pm by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Multi-Input Popup Box
« Reply #13 on: June 19, 2021, 08:43:54 pm »
"We have seen the glitches at midnight."

Wasn't that Shakespeare ? ;)

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Multi-Input Popup Box
« Reply #14 on: June 20, 2021, 12:39:39 am »
I've been doing this in SCREEN 0 for the past 9,000 years.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/