Last week we managed to get MiLo to list on screen all previous sets of generated lottery numbers. A more flexible approach would be to use OPL's dialog functions to construct a small 'browser', with buttons to show the previous number, next number etc.
There's quite a bit of typing, cutting and pasting to do this week, but
all in the same procedure. Find the last procedure in the program (listprev:) and
add in a new LOCAL variable with:
LOCAL k%
Now go down a few lines and change the WHILE...ENDWH loop to be as follows.
Note that the third line, the dTEXT, is very long and probably wrapped in your
browser window - just enter it in one long line on your Psion or compatible:
WHILE 1 REM Do loop until exited with ESC or Cancel button
dINIT "Number archive"
dTEXT "",gen$(A.num1%,2)+"
"+gen$(A.num2%,2)+" "+gen$(A.num3%,2)+"
"+gen$(A.num4%,2)+" "+gen$(A.num5%,2)+"
"+gen$(A.num6%,2)+" "+gen$(A.num7%,2)+"
"+gen$(A.num8%,2)
dBUTTONS
"Previous",%p,"Cancel",27,"Next",%n
k%=DIALOG
IF k%=27 OR k%=0
BREAK
ELSEIF k%=%p
IF POS=1
gIPRINT "Already showing first set of
numbers!"
ELSE
BACK
ENDIF
ELSEIF k%=%n
NEXT
IF EOF
gIPRINT "Already showing last set of
numbers!"
BACK
ENDIF
ENDIF
ENDWH
Before we go through the code and explain what's going on, translate and run it so that you can see what I'm talking about:
Quite clever, isn't it? OPL's excellent dialog functions allow us to build quite a slick little function with only a few lines of program code. I'll take you through it, step by step:
You've seen the WHILE 1 construction before. It's simply a way of
getting a loop to carry on forever until told to stop. Now come three basic
dialog commands. dINIT is needed at the start of every dialog in OPL, as a
way of saying 'Here come some dialog line definitions'; we've included the
optional title in quotes after dINIT as I think dialogs with titles are just
a bit more friendly to the user.
Now to the very long line. As you'll note, it's basically just saying
"Print out each number in the current record with a space between each one".
The extra "", after dTEXT are needed, it's just the way that the command
works (see the OPL manual for further details). Because dTEXT always expects
text or character strings to follow it, we've had to convert each number (that
we previously just PRINTed) into the right form. The function gen$() is
extremely useful in this sort of instance, converting a number to a string of
characters, e.g. the number 34 would be converted by gen$(34.0,2) into the string
"34" (i.e. the characters "3" and "4"). Note that the "2" in the gen$
brackets is fairly irrelevant here but would be use for decimal (floating
point, e.g. 3.56) numbers to indicate how many places we want constructed after
the decimal point. As always, character strings can simply be concatenated
(added together) with the "+" sign, and I've added an extra space ("
")
between each as well, for extra readability.
You'll probably want to do what I did, typing in the first gen$(A.num1%,2)+" "+ and
then cutting and pasting the rest, changing the integer in the middle
afterwards.
Having displayed the list of numbers in the current record on-screen
(within the dialog), the next stage is to provide some controls for moving
backwards and forwards in the archive file. dBUTTONS is handy for this sort of
thing. If you look at the code, you can guess that there will be a button
marked "Previous" that returns the ascii code for "p" when pressed (and indeed
needs the user to press the letter "p" on the 3a/3c, which has no
touch-screen), a "Cancel" button which returns 27 (the ascii code for the
'escape' key) and a "Next" button which returns the code for "n".
The DIALOG command completes the dialog and displays it on-screen.
k% is set to the value of whichever button the user uses to complete the
dialog. All we've got to do now is handle the three possible values:
IF k%=27 OR k%=0 Note that I check for zero as well as 27 because pressing the
Escape key to exit a dialog always returns zero (instead of the more logical
'27' - just one of those things you need to know!). The BREAK command just
quits out of the current WHILE loop, which is exactly what we need. Once out
of the loop, the program CLOSEs the archive file and returns to the main
procedure etc. IF k%=%p If set to this value, the user must have used the "Previous"
button. We use the POS command to check the current record number in the
archive file. If it's already at 1, there isn't a previous record to go to, so
we just put up an error message and carry on. If it's not 1, we use the BACK
command to move the record pointer back one notch, ready for display next time
through the WHILE loop. IF k%=%n If set to this value, the user used "Next" instead. Again,
there's a quick check we need to make. We use NEXT to advance the record
pointer one notch and then check the EOF (End Of File) command. If it comes
up 'true', we know that we were already on the last record in the file and so
we put up an error message and move the pointer back again. If EOF is
'false' it's OK to carry on and we leave the record pointer as it is (advanced
one notch). Hopefully this has all made sense. Do experiment with DIALOGs, they're enormously useful and a great time-saver. For example, we could have coded up graphical buttons for the user to tap on and display routines to show the numbers etc, but it would have been quite long-winded. By using OPL's built-in functions as much as possible you'll save yourself much time and effort!
For example, I used dialogs to great time-saving effect in my commercial Team Psion (on Psion's Games arcade). Here's a screenshot showing how I displayed each segment of the starting grid:
Good stuff. Again, I could have coded the screen in long-winded OPL, with a routine to handle the control buttons, but it would have been slower, less elegant and taken 10 times as long to write!
For those whose code has become mistyped or confused, the full program code is available here as milo19.txt.
Happy coding and I'll see you next week!
Go to next lesson | Programming index