By the end of this reading you should know the following:
openCard, closeCard, preOpenCard, openStack, closeStack, preOpenStack
.openField
message is sent.closeField
and exitField
.pass
and send
commands.Messages. LiveCode is what is called an “event driven” programming environment. When events happen in the LiveCode environment—things like mouse clicks, key presses, and movement between cards—messages are generated and sent to your stack, much like a compulsive play-by-play announcer describing everything that happens in the sporting arena.
Message Handlers. As a LiveCode programmer, you write message handlers that intercept these messages and execute various commands and functions. The basic syntax for writing a message handler, which intercepts and acts on messages sent in LiveCode, looks like this:
on message statement(s) end message
where
message
is any message generated in LiveCode.
statement(s)
is one or more LiveCode statements or commands that should be executed when the message is sent.
There are several messages associated with mouse clicks:
mouseUp
message. This is the most commonly used message handler in button object scripts. The mouseUp
message is sent on the up part of a click.mouseDown
message is sent on the down part of a click. Thus every click generates first a mouseDown
message, then a mouseUp
. The mouseDown
and mouseUp
handlers are often used in pairs to do one thing when the mouse button is clicked down and something else when it is released.
mouseRelease
message is sent to the control that received the mouseDown
when the user releases the mouse outside the clickable area of the object. In this case, no mouseUp
message is sent.These mouse click messages are less commonly used, but still very useful:
mouseDoubleUp
message is sent on the up part of the second click. A mouseUp
message will still be sent on the first click.
mouseDoubleDown
message is sent on the down part of the second click. Every double click generates first a mouseDoubleDown
message, then a mouseDoubleUp
. A mouseDown
message will still be sent on the first down click.mouseStillDown
message is sent repeatedly while the mouse button is held down after the initial mouseDown
. A mouseStillDown
may be used to do something repetitively as long as the mouse is held down. (Note: A mouseStillDown
is not sent after a double click. It only occurs during a single click cycle.)There are four other messages associated with the mouse. These have to do only with the location of the mouse pointer— no click is required to generate them:
mouseEnter
and mouseLeave
messages are often paired together, since they represent reciprocal actions. They are particularly useful for creating dynamic “rollover” actions. A rollover action is when something visually changes about an object when the mouse points to it.mouseWithin
message is sent repeatedly after the initial mouseEnter
while the cursor remains within the rectangular area of an object. A mouseWithin
handler behaves much like mouseStillDown
, but is sent repeatedly whether or not the mouse button is down.
mouseMove
message is sent whenever the user moves the mouse.Theoretically, these messages can be handled by any object with a proper handler. While this is generally true, reality sometimes paints a different picture. Some types of object may not handle messages exactly the same as other types object. You'll have to experiment to discover what works and what doesn't. See the next section, for instance, to see differences in how fields handle various messages.
Because the purpose of fields is different from the purpose of buttons, fields can respond differently to some mouse messages as compared to buttons. The main difference is seen when a field is unlocked. A locked field responds to all mouse click messages in the same way a button does; that means a locked field can have mouseUp
, mouseDown
, mouseRelease
, mouseDoubleDown
, and mouseDoubleUp
handlers, and mouse clicks will trigger all of them, just as in a button.
The situation changes when a field is unlocked. Unlocked fields do not receive mouse click messages at all, so handlers like mouseUp
, mouseDown
, mouseDoubleUp
,etc. are ignored when a field is unlocked. However, once unlocked, fields receive other messages that locked fields do not. These have to do with the fact that the user can choose selection and insert points and change the field text by using the mouse. Instead of the mouse click messages, these messages are sent to unlocked fields:
openField
message is sent to an unlocked field when you click or select text within that field, or when the field receives focus by “tabbing” through a series of fields.closeField
message is sent to a field when the cursor is removed from that field and the field's contents have been changed. If there has been no change made to whatever the field contains, then no closeField
message is sent. exitField
message is generated and sent to the field.These messages allow you to monitor the state of text in a field. For instance, you could enable a Save button if the text of the field has changed, and disable it if it hasn't. It might look something like this:
on closeField enable button "save" end closeField on exitField disable button "save" end exitField
In a similar way, you could use a selectionChanged
handler to enable a cut/copy menu based on whether some text was selected when the selection is changed.
Open and close messages are sent when objects are "opened" and "closed"; that is, when they first come into view (as in the case of cards and groups); or receive "focus"; that is when the mouse or keyboard causes them to become the target object (as in the case of fields.) You have seen how open and close messages work with fields. There are three other object types in LiveCode for which open and close messages are generated—stacks, cards, and background groups.
Open handlers can be used to do things like initial layout setup, showing introduction fields, etc., for when the object first appears. Close handlers are typically used for things like saving answers and generally cleaning up the environment after the current user is finished.
openCard
message is sent to a card when you arrive at that card, and the closeCard
message is sent to the card when you leave for another card.openStack
message is sent to the destination card right after you open a stack. The closeStack
message is sent to the current card when the stack closes (either by quitting the application or by closing the stack window).openBackground
message is sent to the destination card right after you go from a card that does not have a specific background-style group to a card that does have the group. The closeBackground
message is sent to the current card when leaving a card that has a background group to go to one that doesn't have that group.Closely related to open/close messages are the suspend and resume messages. But instead of being generated when a stack has been opened or closed, they are sent when the user changes from one stack to another, as happens when you click on a stack window to bring it to the front:
openStack
and closeStack
and are normally used in conjunction with each other. The resumeStack
message is sent to the current card when a stack window is brought to the front. The suspendStack
message is sent to the current card when something makes its stack no longer the active window.This class of messages is sent to the active/focused control when keys on the keyboard are pressed. If no control is active or focused these messages are sent to the card:
For most LiveCode messages we've talked about, when there is no handler to handle the message as it passes through the hierarchy, it gets ignored. However, there are a few LiveCode messages that have a default behavior:
keyDown
If the active cursor is in an unlocked field, this message causes the character assigned to the key pressed to be entered into the field.tabKey
Moves the insertion point into first (next) editable field.arrowKeys
Navigates the user forward/backward between cards (assuming the "Arrow keys navigate through cards" setting is checked in LiveCode's preferences and the cursor is not in a text field.)When there is a handler for a message like arrowKey
, it intercepts the message and overrides the default behavior. After LiveCode has executed a handler, it considers its task finished and the message which triggered the handler “dies”, that is, it doesn’t continue up the message hierarchy. In some cases this may be what you want. Writing an arrowKey
handler, for example, could prevent users from using arrow keys to navigate into parts of your stack you want to keep secure. However, sometimes you actually want LiveCode to execute a object's handler and then perform its default behavior or execute another handler located further up in the hierarchy along the message path right after that. To make that happen, you would do something similar to this in the object's script:
on mouseUp beep pass mouseUp end mouseUp
The pass
command means that after the object has handled the message, it will be passed to the next level of the hierarchy along the message path for a mouseUp
handler, which could be that in a group or card script, for example. If an appropriate handler is found, it will then execute that handler in the group or card script and stop moving up the levels unless there is also a pass command in that handler.
Note: When the pass command is executed, any remaining statements in the handler are skipped, so this command is almost always placed at the end of a handler or within an if
-control structure.
This command is used to send a message to an object. In this respect it is similar to the pass command. However, with send
you can override the normal message path, allowing greater flexibility with where messages are sent. It also differs from pass in that once the command is executed and the message is sent, the rest of the handler is still executed. The basic syntax is:
send message to object
where
message
is any message, sent as a literal string, and
object
is any object.
A practical example of this command would look something like this:
on mouseUp hide image "flowers" send "mouseUp" to button "Reset" show field "Instructions" end mouseUp
This handler would first hide the image, then send the mouseUp
message to button "reset" (or any other given object). That button would then execute the mouseUp
handler in its script. After that had finished, the original handler would continue executing its handler and would show the image. The strength of this command lies in its ability to provide access to handlers in objects outside the normal message hierarchy. Note that you are not limited to sending the same message as in the enclosing handler. For example, you could also say:
send "openCard" to this card
LiveCode does not just limit you to using the built-in messages like mouseUp
and openCard
. You can also write custom handlers that you can name anything you want. Let’s say, for example, that you wanted a certain number of things to be done when you first come to a card, to set it up for the user. You might also want to have a button on the card that allows the user to reset the controls on the card. We could write a handler like this in the card script:
on resetAll put "Click Start to begin." into field "instruction" enable button "start" hide field "feedback" disable button "nextQuestion" end resetAll
By writing this handler you have essentially created a new command that you can call from anywhere on this card. So in the card script you could do this:
on preOpenCard resetAll end preOpenCard on resetAll put "Click Start to begin." into field "instruction" enable button "start" hide field "feedback" disable button "nextQuestion" end resetAll
Significantly, you could also use this new command from a button on the card. Let’s say you create a button called “reset” on this card. You could write a handler for that button like this:
on mouseUp resetAll end mouseUp
Can you see how this can simplify your scripting and extend the power of LiveCode? By “bundling” commands into custom handlers you can execute batches of commands by simply “calling” the new handler from anywhere in the hierarchy of the object that whose script contains the handler.
We will learn more about writing custom message handlers in a later lesson.