![]() | ![]() | ![]() |
The Wimp Development System for Risc OS |
Download the resource | ![]() |
Over the last two articles we have created the software to set options within the screensaver. Now we can get on with the serious business of writing the screensaver itself.
Before we start, we need to consider what the screensaver has to do, and in addition the extra actions the screenlock must carry out. The screensaver must
The screenlock in addition needs to
Much of the above is fairly straight forward, apart from the check for the mouse leaving the window. This is required in case the user has left the mouse at the point on screen which activates the iconbar and brings it to the front. If this is not counteracted the screenlock is effectively useless. To complicate matters the routine also has to ensure the mouse has not moved into the password input window, in which case window redraw must be curtailed if the software is set to draw a static image, after all there is no point in redrawing the image behind the window.
First of all create a sprite approximately 248 by 79 pixels. Like most of my sprites this started life in Drawworks Millenium. Draw a black square. choose a font colour, a size of 60 in Trinity.Bold.Italic and type Archive. On the next line choose a font size of 18 and type "For RISC OS Users". Using DrawWorks' justify option I then centred the two text items. It's then a simple matter of grabbing as a sprite and trimming to size. For those of you who have found that too energetic, a copy is on this month's disc.
If you want to, you can always design your own masterpiece, but for now keep the sprite to the above dimensions. It won't matter if the sprite is not exactly to size. Save your file as "sprite", although the sprite itself is called "archive".
Load Wimpbasic(WB) and in the Program name field enter 'Screensaver'. Next drag your sprite file to the sprite viewer.
Close the sprite viewer and go to the window editor. Create a new window about 1.5 x 5 inches (3 x 12 cm). The size is not really important. This is the blackout window so set the foreground and background colours to black (colour 7). In window data deselect all window furniture, and in title text enter main. Click Ok. Next go to the window size editor and set the values as shown below. Set the sizes as below then save the window as 'window'.
Figure 1 Blackout window sizes
You need to create a further window, which will be used for inputting the password. Create a text icon with no border and for the text 'Enter Password'. Call this icon legend$. Make sure you modify the icon by unticking the filled option, so that the text doesn't have a grey surround on the marble background.
Next create a writeable field, and call it input$. Make sure the icon is selected and from the menu select 'Amend selected'. In the 'other' field enter D*. If you remember from part one this simply ensures asterisks are printed when the user types anything into the box. Click on ok.
The next bit is optional. Create a text field as per the first icon and amend the text to 'Authorised Access Only', and set the foreground colour to red. call the icon t$. Remember to untick the filled option. Resize the window so that it is about 3.5 by 2 inches ( 9 x 5cm). Remove all window furniture except the title bar. In the title text enter Archive Screenlock. Make sure the moveable field is unticked. The window, when finished, should look similar to the one below.
figure 2 The Password window
Save the window as password.
That's the simple bit over. All we need now is the code to make use of all this. So let's get started by going to the variables editor. Create two groups, mouse and global. In the mouse group create two variables, x% and y%. In the global group create the following variables, time%, mtime%,pass$,lock%,static% and exit%. Close the variables editor and go to the WB main window.
Click in the icon to the left of startup procedure to open the code editor.
The following code will be familiar to those who have typed in the code from the last issue. If you wanted to, you could export the code from the last issue. For those who want the code, enter the following lines
local b$,file$,x%
file$="<Choices$Dir>.scrsavers.archive" x%=openin(file$) if x%=0 then close#x% global:lock%=0 global:static%=0 else close#x% procreadfile(file$) endif global:exit%=0 procopenwin endproc |
I won't make much comment about the code except the part which looks for the choices file. If the user has simply run the screensaver from the test button then the chances are that they won't have run the screen saver set up program. Sensible defaults are set, and it is left at that. I don't think that the screensaver should be writing data. I am all for the user making that decision. If the user tests the screensaver, and doesn't like it, the chances are that they won't want redundant data files stored in !Boot.
Now you can either export readfile from the saver set up program or type in the following lines which will read in the configuration file created by !Sversetup (note the spelling - no a).
defprocreadfile(file$)
local x% x%=openin(file$) input#x%,global:lock% input#x%,global:pass$ input#x%,global:static% close#x% endproc |
Go back to the window editor and open the blackout window. From the menu choose events, and in the subsequent window click on the Null event and keyboard event boxes. The code editor should have opened and created two procedures/ functions. In FNkeyboardevent%(key%) enter the following lines
if global:lock%= 0 then
procexit else opencentred password inputfocus password,password:input$ global:time=time endif =true |
This is designed to pick up key presses, and checking whether the password is set. If the password is unset, then it's a simple matter of shutting the program down, otherwise it's a case of opening the password window.
In the function Procnullhandler enter
local c%
if time-global:mtime%>1000 then procflip else c%=isopen(password) if c%=false then procmousecheck endif endproc |
The first part of the code is to check how long it has been since the last screen update. In this case has 10 seconds elapsed, if the screen is not to be updated, the second part of the code checks to see if the password window is open and if not calls the routine to check the mouse position. The code is written like this to avoid opening the pasword window again. After all, if the window is open then it's likely that the user is entering a password, and would not want to lose what had been typed in because the mouse had been knocked in the process. When writing this software I was amazed how sensitive the mouse is, even to the most trivial of knocks.
Return to the window editor and open the password window. From the menu select event handler. Click on null event and rename the subsequent routine to defprocpassullhandler, and enter the following.
local a%
if time-global:time%>1500 then close password mouse:x%=mousex(window) mouse:y%=mousey(window) a%=isopen(window) if a% then inputfocus window endif endproc |
This checks to see how long the window has been open. If more than 15 seconds have passed since the the last event the window is closed. This is after all partially a screensaver.
The mouse coordinates are updated using the mousex() and mousey() functions built into WB. The parameter is the name of the window in which you want the coordinates read from.
Save the code and from the menu select event handlers. Click on keyboard event and rename it to passkeyevent and enter the following.
if key% =13 then
hide password proccheck endif =true |
This picks up the return key being pressed in the password window, and hides the window (to preserve the user input) and calls the password check routine.
You can now close and save the password window.
Go back to the code editor and create proccheck with the following lines
local a%
if password:input$=global:pass$ then procexit else global:exit%=0 close password mouse:x%=mousex(window) mouse:y%=mousey(window) endif endproc |
The routine checks the user input and acts accordingly.
The code that deals with the incorrect password simply closes the password window, and therefore forgets the user input, and rechecks the position of the mouse, which may have moved. If we don't check and reset the coordinates of the mouse it is likely that the password window will simply reopen again.
Create a new routine procexit with the following lines
if global:exit%=1 then
oscli "unset ScrSaver$running" Sys &400FA,1,433 quit endif endproc |
The oscli command simply unsets the system variable to say that a screensaver is running. This means that Risc OS will run the screensaver if left unattended. The sys command will be discussed later. Create a new procedure defprocflip
local sx%,sy%
if global:static%=0 then global:mtime%=time endproc endif |
This checks to see whether the graphic is static. If it is then it simply resets the timer. The following lines deal with a moving graphic
Output window
background 0,0,0 cls sx%=rnd(screen:width%) sy%=rnd(screen:height%) spriteputat "archive",sx%,-sy% refresh global:mtime%=time endproc |
This simply takes the screen size, and the output command ensures that the sprite is randomly plotted on the archive window, and then resets the timer. Not very exciting I know, but see later!
You can create a further procedure procmousecheck without closing the code editor, with the following lines
local mx%,my%
mx%=mousex(window) my%=mousey(window) if mx%<>mouse:x% or my%<> mouse:y% then if global:lock%=1 then opencentred password inputfocus password,password:input$ global:time%=time else global:exit%=1 endif else global:exit%=0 endif procexit endproc |
The routine first of all checks the x and y position of the mouse. If it has moved then it checks to see whether a password is set and opens the password window as appropiate. If the password is not set it simply sets the exit flag. I have indented this code as it is not complex just difficult to follow.
Create a new procedure procpointerleaving
local b%
b%=mousewindow(password) if b%=true then endproc else openwindow endif B%=isopen(password) if b%= true then opencentred password endproc |
This routine is designed to catch a specific situation. As you know the iconbar can be set to come to the front of the windows when the mouse pointer is left at the bottom of the screen. Well, if that happens it makes the password facility pointless. The code checks first to see if the mouse is going into the password window. If it is, it loses interest and quits the routine. If the mouse is moving into any other window the routine reopens the blackout window. It does not open a new window but simply reopens it at the front.
The code then checks to see whether the password window was open and if it was reopens it for user input, just in case the user has knocked the mouse to the bottom of the screen. You need to reopen the main window in the window editor, and go to window event handlers, and link the code to the pointer leaving event.
I have left the most important procedure to last. Create a procedure procopenwin. The reason? It has some interesting aspects and shows the flexibility of WB.
local dx%,dy%,sprite%,r3%,r4%,sx%,sy%
mouse:x%=mousex(window) mouse;y%=mousey(window) dx%=screen:width% dy%=screen:height% SYS &400FA,0,433 openat window,0,0,dx%,dy% global:mtime%=time inputfocus window sprite%=getspritememory() sys &2e,296,sprite%,"archive" to ,,,r3%,r4% output window cls if global:static%=0 then sx%=(dx%/2)-(r3%) sy%=(dy%/2)-(r4%) spriteputat "archive",sx%,sy% else procflip endif endproc |
So what's going on here. Obviously the mouse coordinates are saved. The screen size is recorded into dx% and dy%. you could use screen:width% etc, but I nominated to keep the code short.
The SYS command is important. It switches off the watchdog system. You may want to debug the program before activating this line. This means that if the password screensaver is activated you cannot get around the password with pressing Alt break. Ensure that there is a space between SYS and the hexadecimal number. The 0 switches watchdog off and the 433 is the program's own internal identity, so that if more than one program switches watchdog off it won't be cancelled by a different program. The 433 by the way was just a number created, it has no meaning in itself. You may remember the command appeared earlier in proccheck when it is reactivated. It is unlikely that there will be a clash of numbers, as very few programs would have cause to switch watchdog off. If you want you can use your own number, but remember to change it in procexit.
The window is then opened and the inital timer set up. The sprite routine is quite interesting in that it uses a mixture of OS sprite commands and WB own sprite routines. The code starts by locating the address of the sprite in memory. It then uses a standard SpriteOP (Sys &2e) command to find the length and width of the sprite, before either plotting centrally on screen or randomly, depending on the options set.
Now compile the program (I usually compile to the Ram disc) as !Archive. Did you rem out the watchdog command? If it compiles run it and see what happens. It is likely that it will run briefly before disappearing, because of the mouse moving when you double click it.
If you are satisfied that it has compiled and is working then remove the rem from the watchdog command and recompile.
Open the screensave application and at the start add the following line to the !run file
Set scrSaver$running Yes
this prevents multiple copies of the screensaver being run.
Save and thats it finished.
Using the obey file open created in the first article, open the filer display where all of the screensavers are and copy the screensaver to this directory. Now open the Archive application and copy the Saversetup program inside.
If you now run !boot and choose screen, the Archive screensaver should be in the list of types. The settings button should also be available, which, when clicked on, will run the saversetup program.
I said some while back that the screen saver was not particuarly exciting. So the challenge is for someone out there to rewrite procflip with something more exciting. If I get any I will come back with an additional article.
The full archive screensaver with source files, is on this month's disc ready for you to install. A full copy of this (and previous articles) is on my website with additional graphics to help you through.
Anyway that's it I hope you have enjoyed this wander around WB. If you have any comments or queries let me know.
Happy programming!!
![]() | ![]() | ![]() |
Previous Article | Tutorial Home | Next Article |