Beginner's Guide to WIMP
Martyn Fox

Chapter 4: Messages and Mouse Clicks

It may seem odd that we have to begin writing our application with the procedure for closing it down, but we don't really want to reset the machine every time we get rid of it. It's a bit like learning to drive a car - one of the first things you have to learn is how to stop! We shall also learn a couple of very useful techniques along the way.

There are usually two ways of closing down an application. One is internally, for example from a menu option; the other is externally, by means of a message through the Wimp system. This is sent to the application when you exit from the desktop or shut down the machine, or select Quit from a Task Manager window menu. We will deal with the second method first, beginning by adding some lines to the Wimp polling loop.

... or select Quit from a Task Manager window menu

... or select Quit from a Task Manager window menu

In the next listing (file page_022), we add a new procedure, PROCreceive, and some extra lines in PROCpoll.

   10 REM >!RunImage
   20 REM (C) Martyn Fox
   30 REM Wimp training program
   40 REM version 0.01 (date)
   50 SYS "Wimp_Initialise",200,&4B534154,"Test" TO ,task%
   60 PROCinit
   70 PROCcreateicon
   80 REPEAT
   90   PROCpoll
  100 UNTIL quit%
  110 PROCclose
  120 END
  130 :
  140 DEFPROCcreateicon
  150 REM creates the application's icon and puts it on the icon bar
  160 !b%=-1:b%!4=0:b%!8=0:b%!12=68:b%!16=68:b%!20=&3002
  170 $(b%+24)="!Test":SYS"Wimp_CreateIcon",,b% TO i%
  190 :
  200 DEFPROCclose
  210 REM tells the Wimp to quit the application
  220 SYS "Wimp_CloseDown",task%,&4B534154
  240 :
  250 DEFPROCpoll
  260 REM main program Wimp polling loop
  270 SYS "Wimp_Poll",,b% TO r%
  280 CASE r% OF
  290   WHEN 6:PROCmouseclick
  300   WHEN 17,18:PROCreceive
  330 :
  340 DEFPROCinit
  350 REM initialisation before polling loop starts
  360 DIM b% 1023
  370 quit%=FALSE
  390 :
  400 DEFPROCreceive
  410 REM handles messages received from the Wimp with reason codes 17 or 18
  420 CASE b%!16 OF
  430   WHEN 0:quit%=TRUE
  460 :

We are beginning to make use of the reason code, which the Wimp_Poll call returns to variable r%.

We're also making our first use of a CASE ... OF statement. The part of the program between 'CASE ... OF' and 'ENDCASE' takes the variable following 'CASE' and compares it with the numbers following the 'WHEN' keywords. If it finds a match on one line, it carries out the instruction on that line, then jumps to 'ENDCASE', ignoring the other 'WHEN' lines.

This CASE ... OF statement checks r% and takes appropriate action according to its value. Line 290 has a call to a procedure we haven't yet written, but line 300 handles reason codes 17 and 18, which are returned when the Wimp sends a message to our application. We need not concern ourselves with the difference between 17 and 18 at this stage.

Message Received

PROCreceive handles messages. The message is contained in the data block returned by Wimp_Poll, beginning at address b%, and we are particularly concerned with the message action code, which is the number in the word at b%+16. We are using another CASE ... OF statement here so that we can add extra lines later, dealing with other message action codes.

At the moment, though, we are only concerned with an action code of zero, which is the instruction from the Wimp to close down. When the program detects this, it simply sets variable quit% to TRUE and returns to the polling loop.

Because quit% is now TRUE, the loop stops repeating and carries straight on to call PROCclose and end the program. We saw this procedure in the previous section but didn't make use of it then. It works rather like PROCinitialise in reverse; again we have to put the ASCII code for 'TASK' in R1 and we put the task handle, which we obtained when we initialised the task, in R0.

When you have copied this version as the !RunImage file, start up the application again, then open the Task Manager window. Click Menu on the name of your application, then follow the menu tree to Task 'Test' and choose Quit. Your application will disappear from the icon bar and the window. The Wimp has sent it a message with an action code of zero, meaning 'Close Down', and it has done as it was told.

Handling Mouse Clicks

There is another way to close down the application at this stage. If you start it up again then click any of the mouse buttons on its icon, you will get an error message saying 'No such function/procedure'. This is because of line 290. We have clicked the mouse over our application's icon, which has caused Wimp_Poll to return with a reason code of 6. This led to a call to PROCmouseclick and an error message, because we haven't written it yet. Basic's response to an error at this stage is to close down the application.

Normally, an application would have a Quit option on its main menu. Creating a menu, however, is a rather complicated business, which we will deal with later. For now, we will use a simpler option - making the task close down when we click the Adjust button on its icon.

We can handle mouse clicks by adding a procedure to the !RunImage file, making a new listing called page_024:

  470 DEFPROCmouseclick
  480 REM handles mouse clicks in response to Wimp_Poll reason code 6
  490 REM b%!0=mousex,b%!4=mousey:b%!8=buttons:
  495 REM b%!12=window handle (-2 for icon bar):b%!16=icon handle
  500 CASE b%!12 OF
  510   WHEN -2:CASE b%!8 OF
  520     WHEN 1:quit%=TRUE
  530   ENDCASE
  560 :

This procedure will handle all the mouse clicks connected with our application. Although it's fairly simple at the moment, it is destined to grow considerably by the time we've finished with it.

Because the procedure deals with various buttons clicked on various icons in various windows, we shall use multiple nested CASE ... OF statements. It may look pointless, using a CASE ... OF with only one WHEN, but we shall be adding a lot more later.

When Wimp_Poll returns with a reason code of 6, this procedure is called and the data block contains the following:

Word   Contents
b%+0Mouse x position
b%+4Mouse y position
b%+8State of mouse buttons
b%+12Window handle
b%+16Icon handle

The REM statement at the beginning of the procedure serves as a reminder of this.

The first thing to find out is which window the mouse was clicked on. At the moment this has to be the icon bar, but we will be adding other windows later on, so we must be sure.

We do this by checking the number in b%+12, which is the window handle. The icon bar has a window handle of -2. This is found in line 510, which leads to another CASE ... OF statement, checking the number in b%+8.

This number tells us the state of the mouse buttons. Think of it as a binary number whose three right-hand bits mirror the state of the three mouse buttons. If the Adjust button is held down, the number will be 1; the Menu button will produce 2 and the Select button 4.

It is a simple matter to set quit% to TRUE when Adjust is clicked and to return to the polling loop, causing the application to close down.

By now, you should be getting a good idea of how multi-tasking programs work. The polling loop, with its repeated calls to Wimp_Poll, is the centre of the whole operation. Each time the program returns from Wimp_Poll, we check the reason code, take whatever action is necessary and dive back into Wimp_Poll again to let other applications have a go.

Ideally, anything our program does between returning from Wimp_Poll and calling it again should take as little time as possible, as none of the other applications can function while it's doing it. If you want to do something that may last for some time, such as loading a file from a disc, it's best to switch on the Hourglass before you start, and switch it off again when you have finished. This indicates that the machine is still functioning, but that multi-tasking has temporarily been suspended.

In the process of learning how to close down our application, we have set in place the procedures for handling Wimp messages and dealing with mouse clicks. We shall make much more use of both of these later on.

previousmain indexnext

© Martyn & Christine Fox 2004