Figure 23-2 Visible and Generic Object Trees

The visible object tree is linked to the generic object tree through the 
GenView-VisContent link. VisComp objects may have children; Vis objects 
may not. (Each object shown simply has the suffix Class removed from its 
class type.)
Figure 23-1 Visible Class Tree

All the classes shown have the properties of VisClass and can be used in an 
application's visible object tree. Visible objects are more flexible but require 
more programming than do generic objects.
Figure 23-0

Display 23-0

SwatDisplay 23-0

Table 23-0
Figure 23-3 Drawing Order of Vis Objects

Since the large object is the first child, it is 
drawn first. The second child is drawn on 
top of it.
Figure 23-4 Adding a Visible Child

Adding an entire visible branch into a visible tree is simple. The line of code 
above shows how to add the Comp object into the tree as the Top object's 
second child. (The labels act as the object names for this example.)
Figure 23-5 Drawing in a Large Document

Both of the shaded coordinate spaces represent a "local" 16-bit graphics space 
within the larger, 32-bit space. The application draws first in the shaded area 
labeled "1." It then does an extended translation, moving the origin of the 
local 16-bit space to "2." It can then execute all graphics commands as if the 
origin were at the new origin of the local space.
See Also

"The GEOS User 
Interface," 
Chapter 10 of the 
Concepts Book, also 
describes visible 
classes and visible 
trees.
See Also

Mouse events are 
referenced in "System 
Classes," Chapter 1, 
starting on 
23VisClass

SOURCES:TICTAC

The visible classes-VisClass, VisCompClass, VisContentClass, and 
VisTextClass-can be extremely useful to application developers. They 
provide a flexibility of display and use that is unavailable with the generic UI 
objects. Among other features, visible objects provide the hooks for and basic 
functionality of custom drawing, custom input handling, and custom 
geometry management.

VisClass is the parent class of all the visible classes and all visible UI objects. 
VisClass objects, by themselves, do nothing; VisClass must be subclassed 
and the objects must be placed in a visible object tree as children of a 
VisCompClass object. Together, VisClass and VisCompClass provide a 
large amount of the functionality required for creating a hierarchy of 
non-overlapping objects.

Many applications will use both VisClass and VisCompClass as well as 
VisContentClass. Before reading this chapter, however, you should be 
familiar with the concepts of the generic UI and with basic GEOS 
applications. You should have created a simple application to get familiar 
with the GEOS system and Goc, and you should be relatively familiar with 
the GenView.

You should also become familiar with both VisContentClass and 
VisCompClass; both of these classes and their relationship to VisClass are 
described in the following sections. This chapter provides a starting point 
and most of the specifics for someone learning about the visible world. You 
would also do well to read "The GEOS User Interface," Chapter 10 of the 
Concepts Book.

	23.1	Introduction to VisClass


VisClass is one of the three visible classes you'll have to have a working 
knowledge of in order to use visible objects. Both of the others, 
VisCompClass and VisContentClass, are its subclasses, and both are 
important in visible object trees. However, VisClass provides the heart of the 
visible world.

VisClass objects do nothing useful by themselves. When you subclass 
VisClass and add your own methods, however, the real power of the visible 
classes can be used without the programmer having to worry about the nuts 
and bolts of most UI issues. These classes inherently provide the following 
features:

Knowledge of Visible Bounds
Every visible object has an instance data field that defines the 
object's bounds in the GEOS graphic coordinate space. These 
bounds are used for many purposes, including drawing and 
input handling. See "Positioning Visible Objects" on page 1338.

Comprehensive Visual Updating
When a visible object is included in an object tree displayed by 
a GenView object, the system automatically tells the object 
when it must redraw itself. For example, when the view scrolls 
or when part of the window becomes exposed, the system will 
send a drawing message through the visible tree; the objects 
then draw themselves at the proper location in the document 
space, and the view window is updated. See "Drawing to the 
Screen" on page 1315.

Geometry Management
When visible objects are arranged as children of a VisComp or 
a VisContent object, they can be set up to update their size and 
position appropriate to the current window and view context. 
The VisComp and VisContent classes provide extensive and 
sophisticated child management functions, though custom 
management is also allowed and is often used. See "Positioning 
Visible Objects" on page 1338, especially the messages 
MSG_VIS_RECALC_SIZE and MSG_VIS_POSITION_BRANCH in 
section 23.4.3.3 on page 1343.

Object Tree Manipulation
VisClass objects can not have children, but they can be 
children of VisCompClass and VisContentClass objects. All 
of these classes support extensive tree operations including 
passing messages up the tree, passing messages down the tree, 
adding branches, removing branches, and moving branches. 
See "Working with Visible Object Trees" on page 1373.

Mouse Event Handling
When an input event occurs over the GenView window in which 
the visible tree is displayed, that event is immediately passed 
on to the VisContent object. The event then travels down the 
visible object tree (automatically) until it is handled by some 
visible object. Most often, the event is handled by the leaf object 
with its visible bounds directly under the mouse pointer. 
Individual Vis objects can also grab the mouse so that they 
receive input events that occur even outside their bounds. See 
both "Handling Input" on page 1351 and "Input," Chapter 11 of 
the Concepts Book.

Keyboard Event Handling
A visible object can grab the keyboard input stream and receive 
keyboard events as they occur. Typically, certain keystrokes 
will be intercepted by the specific UI even if a visible object has 
the keyboard grab; this ensures the object won't usurp 
functions expected by the user from his specific UI. (The object 
can, however, override keystroke interception, though this is 
strongly discouraged.) See "Input," Chapter 11 of the Concepts 
Book.

Interaction with Input Hierarchies
VisClass objects have an inherent knowledge of the input 
hierarchies. Many visible objects may need to interact with the 
Focus and Target input hierarchies especially, and they can 
also interact with the Model hierarchy as well. See "Input," 
Chapter 11 of the Concepts Book.

Use of VisMonikers
Typically, visible objects will draw themselves in their entirety 
and will not need visual monikers. Monikers are typically 
labels attached to objects that get displayed either on or near 
the object. Visual monikers are most frequently used with 
generic UI objects, but they can be set up and used with visible 
objects as well. See "Using Visual Monikers" on page 1328.

Standard MetaClass Functions
Because VisClass is a subclass of MetaClass, it inherits all 
the basic, standard object functions of that class (e.g., state 
saving, instantiation and initialization, detaching and 
destruction, etc.). See "MetaClass" on page 41 of "System 
Classes," Chapter 1.

Many programmers new to object-oriented programming may think that 
visible objects are used only in certain circumstances. On the contrary, visible 
objects may be used for nearly any purpose and to provide nearly any 
application-specific graphical or user interface functions. When used 
properly, visible objects can relieve you of hours of writing specialized code.

Programmers new to OOP may need to practice with several small 
applications in order to gain experience using visible objects. You can also 
study the sample applications, many of which use visible objects extensively.

Visible objects are most useful when you have well-defined items that must 
appear on the screen or interact with the user. Pieces in a board game provide 
a good example: Each piece has its own visual representation, and each piece 
has a special set of behaviors that depend on user actions and game context. 
Therefore, it makes sense to have each piece be an object of VisClass.

Another, less immediately obvious, example might be a program that 
represents maps on the screen. The map itself could be stored as a visible 
composite object (VisCompClass), and each of the major subdivisions on the 
map could be a visible object. For example, in a map of the United States, the 
country would be a VisComp object, and each state could be a Vis object. 
Taken one step further, each state could be a composite object, and each 
county in the state a visible child of the state. Another step turns the counties 
into composite objects and each town a visible object. This arrangement lends 
itself to a tree structure, which is how visible objects are stored.

Another example is a spreadsheet application. The spreadsheet itself could 
be one composite object containing a number of row objects. Each row object 
is a composite that holds a number of cell objects. Each cell is a visible object 
with the functions of the cell built into it. The row and spreadsheet 
composites can use the geometry manager to arrange the cells properly, 
thereby making the programmer free of ever having to worry where the cells 
are in the document. The visible object tree will automatically pass input 
events to the cell under the mouse pointer. Entire rows can be created, 
destroyed, drawn, erased, or moved with a few simple commands by the 
programmer.

	23.2	The Visible Class Tree

As stated earlier, the visible class tree consists of four classes. The 
relationship between these classes is shown in Figure 23-1.

VisClass	This is the parent class of the visible tree. It contains the basic 
functionality common to every visible object and is the subject 
of this chapter.

VisCompClass
A subclass of VisClass, this class has the added ability to have 
and arrange children in the visible tree. It has sophisticated 
geometry management functions built in and can be used as an 
organizational object.

VisContentClass
A subclass of VisCompClass, this class is used only as the 
content of a GenView. The VisContent has default handlers for 
many messages sent out by the view, and it interacts with the 
view window to display the visible object tree. Every visible 
object tree, to be displayed in a GenView, must have a 
VisContent as its root object.

VisTextClass
This class, not discussed in this chapter, is a visible version of 
the GenTextClass. It provides a nearly full-featured word 
processing object that can be put in the visible tree.

The first three of these classes are used extensively by many applications. 

	23.3	VisClass Instance Data

VisClass has seven different instance data fields as shown in Code 
Display 23-1. Each of these fields is discussed in detail in the following 
sections, and each may be set or reset during execution by sending the visible 
object certain messages.

Several of the instance fields will never be used by the application 
programmer. Most likely, you will work directly with the VI_bounds field and 
perhaps the VI_attrs or VI_geoAttrs fields. It's unlikely you will need to use 
the others unless you're doing something quite unusual.

Code Display 23-1 VisClass Instance Data

/* This is the definition of the VisClass instance data fields with some comments
 * as to their use. */

	/* VI_bounds
	 * VI_bounds is a Rectangle structure defining the outermost boundaries of
	 * the visible object. */

    @instance Rectangle				VI_bounds = {0, 0, 0, 0};

	/* VI_typeFlags
	 * VI_typeFlags is a record containing eight flags that determine the
	 * type of the visible object. None are set by default. */

    @instance VisTypeFlags				VI_typeFlags = 0;
	/* Possible flags:
	 * VTF_IS_COMPOSITE				VTF_IS_WINDOW
	 * VTF_IS_PORTAL				VTF_IS_WIN_GROUP
	 * VTF_IS_CONTENT				VTF_IS_INPUT_NODE
	 * VTF_IS_GEN				VTF_CHILDREN_OUTSIDE_PORTAL_WIN */

	/* VI_attrs
	 * VI_attrs is a record that contains eight attribute flags for the
	 * object. Those set by default are shown. */

    @instance VisAttrs				VI_attrs = (VA_MANAGED | VA_DRAWABLE |
					   VA_DETECTABLE | VA_FULLY_ENABLED);
	/* Possible flags:
	 * VA_VISIBLE				VA_FULLY_ENABLED
	 * VA_MANAGED				VA_DRAWABLE
	 * VA_DETECTABLE				VA_BRANCH_NOT_MINIMIZABLE
	 * VA_OLD_BOUNDS_SAVED				VA_REALIZED */

	/* VI_optFlags
	 * VI_optFlags is a record containing eight window update flags.
	 * The flags set by default are shown. */

    @instance VisOptFlags				VI_optFlags = (VOF_GEOMETRY_INVALID |
					VOF_GEO_UPDATE_PATH | VOF_WINDOW_INVALID |
					VOF_WINDOW_UPDATE_PATH |
					VOF_IMAGE_INVALID |
					VOF_IMAGE_UPDATE_PATH);
	/* Possible flags:
	 * VOF_GEOMETRY_INVALID				VOF_GEO_UPDATE_PATH
	 * VOF_IMAGE_INVALID				VOF_IMAGE_UPDATE_PATH
	 * VOF_WINDOW_INVALID				VOF_WINDOW_UPDATE_PATH
	 * VOF_UPDATE_PENDING				VOF_EC_UPDATING */

	/* VI_geoAttrs
	 * VI_geoAttrs is a record of eight geometry management flags. */

    @instance VisGeoAttrs				VI_geoAttrs = 0;
	/* Possible flags:
	 * VGA_GEOMETRY_CALCULATED				VGA_NO_SIZE_HINTS
	 * VGA_NOTIFY_GEOMETRY_VALID				VGA_DONT_CENTER
	 * VGA_USE_VIS_SET_POSITION				VGA_USE_VIS_CENTER
	 * VGA_ALWAYS_RECALC_SIZE				VGA_ONLY_RECALC_SIZE_WHEN_INVALID

	/* VI_specAttrs
	 * VI_specAttrs is a record containing eight flags used when the visible
	 * object is part of a specific UI library. This field is rarely if ever
	 * used by applications. */

    @instance SpecAttrs				VI_specAttrs = 0;
	/* Possible flags:
	 * SA_ATTACHED				SA_REALIZABLE
	 * SA_BRANCH_MINIMIZED				SA_USES_DUAL_BUILD
	 * SA_CUSTOM_VIS_PARENT				SA_SIMPLE_GEN_OBJ
	 * SA_CUSTOM_VIS_PARENT_FOR_CHILD
	 * SA_TREE_BUILT_BUT_NOT_REALIZED */

	/* VI_link
	 * VI_link contains an object pointer to the visible object's next sibling
	 * in the tree. Note that VisClass has no corresponding @composite field;
	 * if the object is to have children, it must be of class VisCompClass.

    @instance @link				VI_link;



	23.3.1	VI_bounds

The VI_bounds field is a Rectangle structure containing four values: The 
left, top, right, and bottom outer bounds of the object. The bounds of a visible 
object describe the object to the rest of the world: the input manager and UI 
use them to determine when the mouse pointer is over the object, and the 
object's visible parent (if any) uses them to figure out the total geometry of all 
its children.

The VI_bounds field is very important to nearly all visible objects. In fact, 
section 23.4.3 on page 1338 is devoted to this field and how it is used. For full 
information on visible bounds, see that section.

	23.3.2	VI_typeFlags

VI_typeFlags, MSG_VIS_SET_TYPE_FLAGS, 
MSG_VIS_GET_TYPE_FLAGS

The VI_typeFlags field is a bitfield record containing eight flags. These flags 
determine the type of the visible object and are used primarily by the UI and 
the windowing system. When used at all, these flags are typically set in the 
object's definition or when the object is first created, and they are rarely 
changed dynamically by an application. The eight flags in this record are 
listed below. The record is of type VisTypeFlags.

VTF_IS_COMPOSITE
This flag is set if the object is of VisCompClass rather than 
VisClass. This flag indicates the object may have children 
(normal VisClass objects can not have children). Because this 
is not the only difference between these classes, changing this 
flag can have unpredictable results.

VTF_IS_WINDOW
This flag is set if the object creates a window via the window 
system in order to display itself and its children. This flag 
implies the object must also have VTF_IS_COMPOSITE set, 
meaning the object must actually be of VisCompClass and not 
VisClass. If this flag is set, the UI will assume that the 
VI_bounds field of the object represents the current size of the 
window. Objects with the VTF_IS_WINDOW flag set are skipped 
by the normal input and output messages such as 
MSG_VIS_DRAW and MSG_META_START_SELECT; these 
messages will be passed directly to the object's appropriate 
child. VTF_IS_WINDOW and VTF_IS_PORTAL are mutually 
exclusive.

VTF_IS_PORTAL
This flag is set if the object is a portal. A portal is an object that 
has its own window and appears in its parent's window. A 
portal differs from a window (VTF_IS_WINDOW) in that the 
window has no part of itself drawn in its parent window. This 
flag implies that the VTF_IS_COMPOSITE flag must also be set 
indicating the object may have visible children. All visible 
children of a portal will appear in the portal's associated 
window if VTF_CHILDREN_OUTSIDE_PORTAL_WIN is set. The 
object itself may display portions of itself within its parent's 
window, though; an example of this is the UI's implementation 
of the GenDisplayControl object, which manages several child 
windows within its own window area. Its border is drawn in the 
parent window, then its window is defined to be one pixel inside 
this border. VTF_IS_PORTAL and VTF_IS_WINDOW are 
mutually exclusive.

VTF_IS_WIN_GROUP
This flag is set for the top visible object in a visible branch 
which makes that branch a realizable entity. This flag implies 
that both VTF_IS_COMPOSITE and VTF_IS_WINDOW must be 
set as well. An example would be the specific UI's 
implementation of a GenPrimary object-if the primary is not 
visible, none of its children may be visible (with some 
exceptions).

VTF_IS_CONTENT
This flag is set if the object is the output of a window object. 
Typically, this will be set only if the object is of 
VisContentClass (not for VisClass or VisCompClass). Note 
that if this is set, both VTF_IS_WINDOW and 
VTF_IS_WIN_GROUP must also be set.

VTF_IS_INPUT_NODE
This flag is an optimization bit. It is set if the object controls 
input flow (such as a VisContent) or is a target or focus node 
that is not a window group (VTF_IS_WIN_GROUP). 
MSG_VIS_VUP_ALTER_INPUT_FLOW is sent directly to objects 
with this bit set unless there is a need for them to actually use 
the VUP mechanism, as is the case with mouse grabs in a 32-bit 
content. Similarly, MSG_META_MUP_ALTER_FTVMC_EXCL, 
MSG_VIS_FUP_QUERY_FOCUS_EXCL, and 
MSG_VIS_VUP_QUERY_FOCUS_EXCL are sent to the first 
visible object up the tree that either is a window group or has 
this bit set.

VTF_IS_GEN
This flag is set if the visible object is the specific UI counterpart 
to a generic object. This flag must be set for the object to handle 
messages that begin MSG_SPEC. The only objects that will ever 
have this flag set are those in Specific UI libraries.

VTF_CHILDREN_OUTSIDE_PORTAL_WIN
This flag is set if children of a portal object may appear in the 
object's parent window rather than in the portal's 
specially-created window. The VTF_IS_PORTAL flag must also 
be set for this object. An example of this is the specific UI's 
representation of a GenView object and its children; the view's 
children appear along the edges of the view window rather 
than inside it. The GenDisplayControl, by contrast, has all its 
children appearing within its window; thus, it does not have 
this flag set.

Although the VI_typeFlags record will rarely be changed at run-time, you can 
set new values by sending MSG_VIS_SET_TYPE_FLAGS to the visible object 
while it is realized. To retrieve the current type flags, send the object a 
MSG_VIS_GET_TYPE_FLAGS.

n	MSG_VIS_SET_TYPE_FLAGS



void	MSG_VIS_SET_TYPE_FLAGS(

	VisTypeFlags		flagsToSet,

	VisTypeFlags		flagsToClear);

This message causes the object to set its VI_typeFlags field to the values 
passed. The flagsToSet parameter will be OR-ed with VI_typeFlags, and the 
flagsToClear parameter will be logically inverted and then AND-ed with the 
field. The clear operation will occur after the set. Therefore a flag set in both 
parameters will be cleared by this message.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	flagsToSet	A record of VisTypeFlags indicating which flags 
are to be set for the object.

flagsToClear	A record of VisTypeFlags indicating which flags 
are to be cleared for the object (a flag set in 
flagsToClear will be cleared in VI_typeFlags).

Return:	Nothing.

Interception:	Unlikely.

n	MSG_VIS_GET_TYPE_FLAGS



VisTypeFlags MSG_VIS_GET_TYPE_FLAGS();

This message returns a visible object's current VI_typeFlags field.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	None.

Return:	A byte of VisTypeFlags representing the object's current VI_typeFlags 
field.

Interception:	Unlikely.

	23.3.3	VI_attrs

VI_attrs, MSG_VIS_GET_ATTRS, MSG_VIS_SET_ATTRS

The VI_attrs field is a record of eight flags (VisAttrs)that determine the 
general visible attributes of the object. These attributes may be changed on 
the fly and often are. Applications that don't involve visible tree operations 
(adding, removing, or moving branches) probably will not change these 
attributes dynamically.

To set the flags after the object has been instantiated, send it a 
MSG_VIS_SET_ATTRS with the appropriate flags to be set. To retrieve the 
VI_attrs record, send the object a MSG_VIS_GET_ATTRS. The VA_REALIZED 
flag may not be changed with MSG_VIS_SET_ATTRS.

The eight flags of the VisAttrs record are listed below:

VA_VISIBLE	This flag is effective only for window group objects (those with 
VTF_IS_WIN_GROUP set in VI_typeFlags) and is ignored for 
other objects. If set, it indicates that the visible branch headed 
by this object can be made visible as soon as it is linked visibly 
to another visible branch. For example, a window group object 
may have this bit set and not be on the screen if its parent 
window group is not set VA_VISIBLE; as soon as the parent 
window group becomes VA_VISIBLE, though, the entire branch 
will become visible.

VA_FULLY_ENABLED
This flag is normally set for visible objects. If it is set, the object 
is fully enabled when visible on the screen. If not set, the object 
is not fully enabled-the object will typically be drawn in a 50% 
pattern (grayed out) and will not receive click events. This flag 
works even for normal visible objects, though this behavior is 
seen almost exclusively with generic UI objects.

VA_MANAGED
This flag indicates that the object's location is managed by its 
parent. If the flag is set, space is set aside in the parent 
composite by the geometry manager. When the window 
displaying this object changes, the geometry will have to be 
calculated. If this flag is not set, the object can alter its own 
location and bounds without affecting the parent's geometry.

VA_DRAWABLE
This flag indicates whether the object is drawn or invisible. If 
the flag gets set or reset during execution, the rectangle defined 
by its VI_bounds field will automatically be marked invalid.

VA_DETECTABLE
This flag, when set, indicates that the object might respond to 
mouse, pointer, keyboard, or other similar events. If the flag is 
reset (such as with display-only objects), its parent composite 
object will not bother passing it these events. This flag must be 
set if the object is a window composite. If the status of this flag 
is changed during execution, the object's grab state will not 
change. For example, if the object has the mouse grab when a 
MSG_VIS_SET_ATTRS resets the flag, the object will retain the 
mouse grab until it is released or preempted normally.

VA_BRANCH_NOT_MINIMIZABLE
This flag is used only by the visible counterparts of generic UI 
objects. If set, it indicates that this branch (e.g., a 
GenInteraction and its children) stays visible and usable even 
when the parent primary window is minimized.

VA_OLD_BOUNDS_SAVED
This flag, when set, causes the geometry manager to store the 
object's old bounds when its VI_bounds field changes. The old 
bounds are stored in a TEMP_VIS_OLD_BOUNDS vardata field.

VA_REALIZED
This flag indicates whether the object is visibly open on the 
screen-i.e., whether it is positioned on an open window. If the 
flag is set, the object is visible on the screen. When the object is 
no longer visible on the screen, this flag is reset. This flag may 
not be altered by MSG_VIS_SET_ATTRS; it may only be changed 
by MSG_VIS_OPEN (which sets the flag) and MSG_VIS_CLOSE 
(which resets it).

n	MSG_VIS_SET_ATTRS



void	MSG_VIS_SET_ATTRS(

	VisAttrs		attrsToSet,

	VisAttrs		attrsToClear,

	VisUpdateMode		updateMode);

This message sets the object's VI_attrs field to the values passed. The 
attrsToSet parameter will be OR-ed with VI_attrs, and the attrsToClear 
parameter will be logically inverted and then AND-ed with the field. The clear 
operation will occur after the set, and therefore a flag set in both parameters 
will be cleared. The updateMode parameter indicates when the visual update 
of the object should occur after the new attributes have been set.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	attrsToSet	A record of VisAttrs indicating which flags are to 
be set for the object.

attrsToClear	A record of VisAttrs indicating which flags are to 
be cleared for the object (a flag set in attrsToClear 
will be cleared in VI_attrs).

updateMode	A VisUpdateMode indicating when the object 
should be visually updated on the screen.

Return:	Nothing.

Interception:	Unlikely.

Warnings:	Not all flags in the VI_attrs record may be set with this message.

n	MSG_VIS_GET_ATTRS



VisAttrs	MSG_VIS_GET_ATTRS();

This message returns a visible object's current VI_attrs field.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	None.

Return:	A byte of type VisAttrs representing the current flags set in the object's 
VI_attrs field.

Interception:	Unlikely.

	23.3.4	VI_optFlags

VI_optFlags, MSG_VIS_GET_OPT_FLAGS

The VI_optFlags field is a VisOptFlags record containing eight flags. These 
flags are set and used by the geometry manager to mark which objects need 
to be updated and how. The flags can not be set individually by applications; 
however, they can be retrieved with the message MSG_VIS_GET_OPT_FLAGS. 
It is unlikely that your code will ever access these flags directly. The eight 
flags in this field are listed below.

VOF_GEOMETRY_INVALID
This flag indicates that the general geometry of this object has 
become invalid (with a MSG_VIS_MARK_INVALID). This is used 
primarily when an object knows that its bounds must be 
recalculated or re-verified and that any change must be 
reflected in its parent window. This flag will be reset when a 
geometry update resolves the object's bounds. Typically, this 
will occur with a window update message such as 
MSG_VIS_UPDATE_WIN_GROUP.

VOF_GEO_UPDATE_PATH
This flag, also set by MSG_VIS_MARK_INVALID, marks a trail of 
objects that all must have their geometry updated.

VOF_IMAGE_INVALID
This flag indicates that the image of the object or the bounds of 
a windowed object have changed and therefore need to be 
updated. This flag is set by MSG_VIS_MARK_INVALID. The 
image redraw will occur the next time one of the window 
update messages is used on the object's visual branch. This flag 
will be reset when a visual update redraws the object. 
Typically, this will occur with MSG_VIS_UPDATE_WIN_GROUP 
or another window update message.

VOF_IMAGE_UPDATE_PATH
This flag, also set by MSG_VIS_MARK_INVALID, marks a trail of 
objects that must have their images updated.

VOF_WINDOW_INVALID
This flag indicates that the window the object resides in needs 
to be opened or closed, or that the object itself needs to be 
opened or closed via MSG_VIS_OPEN or MSG_VIS_CLOSE. It is 
set by MSG_VIS_MARK_INVALID. This flag will be reset when a 
visual update occurs on the window group. Typically, this will 
occur with a window update message such as 
MSG_VIS_VUP_UPDATE_WIN_GROUP. (This message should be 
called whenever an object is added to a visible tree; it ensures 
the object will be properly opened.)

VOF_WINDOW_UPDATE_PATH
This flag, also set by MSG_VIS_MARK_INVALID, marks a trail of 
window objects that all must have their windows and 
open/closed state updated.

VOF_UPDATE_PENDING
This flag indicates that the object has an unprocessed 
MSG_VIS_UPDATE_WIN_GROUP in its event queue.

VOF_EC_UPDATING
This flag is used by the VisClass error-checking code only. It 
indicates that a visible branch is currently being updated; the 
system checks it to make sure nested updates do not occur.

n	MSG_VIS_GET_OPT_FLAGS



VisOptFlags MSG_VIS_GET_OPT_FLAGS();

This message returns the current VI_optFlags field of the object.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	None.

Return:	A byte record of VisOptFlags reflecting the current settings in the 
object's VI_optFlags field.

Interception:	Unlikely.

See Also:	MSG_VIS_MARK_INVALID.

	23.3.5	VI_geoAttrs

VI_geoAttrs, MSG_VIS_SET_GEO_ATTRS, MSG_VIS_GET_GEO_ATTRS

The VI_geoAttrs field is a VisGeoAttrs record of eight flags that determine 
the state of the object's geometry. They can be set and reset during execution 
to dynamically change the geometry behavior of the object. None of the flags 
is set by default. To set the flags, send the object a 
MSG_VIS_SET_GEO_ATTRS. The flags can be retrieved with a 
MSG_VIS_GET_GEO_ATTRS. The eight flags in this record are listed below.

VGA_GEOMETRY_CALCULATED
This flag indicates whether the object has ever been calculated. 
If the flag is clear, the object's geometry is about to be 
calculated. An object may use this flag if it has a particular 
desired size. This flag is cleared before a geometry 
recalculation by MSG_VIS_RESET_TO_INITIAL_SIZE.

VGA_NO_SIZE_HINTS
This flag is used by the Specific UI library to determine 
whether the object has any sizing hints or not. If the flag is not 
set, the object has one or more sizing hints (e.g., 
HINT_INITIAL_SIZE or HINT_FIXED_SIZE).

VGA_NOTIFY_GEOMETRY_VALID
If this flag is set, the geometry manager will notify the object 
when its geometry messages have all been handled and the 
object's geometry is set. Notification will be in the form of 
MSG_VIS_NOTIFY_GEOMETRY_VALID. This flag may be used 
by visual objects for calculations or other sizing once geometry 
is redone but before redrawing occurs.

VGA_DONT_CENTER
This flag, when set, allows the object to individually override 
its parent's centering behavior. The object will instead appear 
at either the left edge of a vertical composite or the top edge of 
a horizontal composite.

VGA_USE_VIS_SET_POSITION
This flag is set to indicate that the object does not use the 
default handlers for MSG_VIS_SET_POSITION and 
MSG_VIS_POSITION_BRANCH. This flag provides an 
optimization that allows static calls to the geometry manager.

VGA_USE_VIS_CENTER
If this flag is set, the geometry manager will use the standard 
VisClass or VisCompClass center message to calculate the 
object's center. Unless an object is using some unusual 
centering behavior, it should have this flag set. This flag allows 
the geometry manager to speed up calculations for normal 
center behavior.

VGA_ONLY_RECALC_SIZE_WHEN_INVALID
This flag indicates that the object's size should be recalculated 
only when its geometry is marked invalid. That is, once the 
object's geometry is calculated, it will always return the same 
size until its geometry is once again marked invalid. Because 
the geometry manager often queries objects for their sizes, 
most objects should have this flag set. It allows the geometry 
manager to speed up calculations.

VGA_ALWAYS_RECALC_SIZE
This flag avoids optimizations that do not recalculate the 
object's size when passed its current size. Though not often 
used, this flag may be needed in certain situations (e.g., when 
a composite object must expand to fit and center its children).

n	MSG_VIS_SET_GEO_ATTRS



void	MSG_VIS_SET_GEO_ATTRS(

	VisGeoAttrs		attrsToSet,

	VisGeoAttrs		attrsToClear,

	VisUpdateMode		updateMode);

This message causes the object to set its VI_geoAttrs field to the values 
passed. The attrsToSet parameter will be OR-ed with VI_geoAttrs, and the 
attrsToClear parameter will be logically inverted and then AND-ed with the 
field. The clear operation will occur after the set, and therefore a flag set in 
both parameters will end up cleared. Many of the attributes in this record are 
used only by Specific UI libraries and should not be altered by applications.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	attrsToSet	A record of VisGeoAttrs indicating which flags are 
to be set for the object.

attrsToClear	A record of VisGeoAttrs indicating which flags are 
to be cleared for the object (a flag set in 
attrsToClear will be cleared in VI_geoAttrs).

updateMode	A VisUpdateMode indicating when the object 
should be visually updated on the screen.

Return:	Nothing.

Interception:	Unlikely.

n	MSG_VIS_GET_GEO_ATTRS



VisGeoAttrs MSG_VIS_GET_GEO_ATTRS();

This message returns a visible object's current VI_geoAttrs field.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	None.

Return:	A record of type VisGeoAttrs reflecting the flags currently set in the 
object's VI_geoAttrs field.

Interception:	Unlikely.

	23.3.6	VI_specAttrs

VI_specAttrs, MSG_SPEC_SET_ATTRS, MSG_SPEC_GET_ATTRS

The VI_specAttrs field is a record of eight flags. This field is accessed only by 
objects that are part of a Specific UI library. Applications will almost never 
access this field or use its flags. Documentation on creating specific UI 
libraries may be published under separate cover.

n	MSG_SPEC_SET_ATTRS



void	MSG_SPEC_SET_ATTRS(

	SpecAttrs		attrsToSet,

	SpecAttrs		attrsToClear,

	VisUpdateMode		updateMode);

This message sets the current VI_specAttrs field to the values passed. A flag 
set in both attributes parameters will be cleared.

Source:	Unrestricted.

Destination:	Any visible object used as a specific UI object.

Parameters:	attrsToSet	A record of SpecAttrs indicating which flags are to 
be set in the object's VI_specAttrs field.

attrsToClear	A record of VisAttrs indicating which flags are to 
be cleared for the object (a flag set in attrsToClear 
will be cleared in VI_specAttrs).

updateMode	A VisUpdateMode indicating when the object 
should be visually updated on the screen.

Return:	Nothing.

Interception:	Unlikely.

n	MSG_SPEC_GET_ATTRS



SpecAttrs MSG_SPEC_GET_ATTRS();

This message returns a visible object's current VI_specAttrs field. This field is 
used only by Specific UI libraries and is meaningful only for objects in these 
libraries.

Source:	Unrestricted.

Destination:	Any visible object that is used as a specific UI object.

Parameters:	None.

Return:	A byte of type SpecAttrs indicating which flags are set in the object's 
VI_specAttrs field.

Interception:	Unlikely.

	23.3.7	VI_link

VI_link

The VI_link field holds the optr of the visible object's next sibling in the 
visible object tree. This field may not be accessed directly by applications but 
may be set or changed with the various visible tree messages. For full 
information on how to build and manipulate visible object trees, see section 
23.5 on page 1373.

	23.4	Using VisClass

As stated earlier, visible objects are nearly useless unless you subclass one of 
the visible classes and handle certain messages. Although there's a lot of 
functionality built into VisClass and its subclasses, they must be customized 
to be of any use. In addition, visible objects must be put into a visible tree and 
connected to a GenView or other windowed UI object to be displayed.

	23.4.1	Basic VisClass Rules

To use visible objects, you must subclass the Vis classes and create a visible 
object tree. Otherwise, the visible objects will not be able to display 
themselves or accept user input, the two things that make visible objects 
worthwhile.

Nearly all visible objects you use will at least display themselves on the 
screen. Some may accept mouse or keyboard input; some may move 
themselves around the screen, resize themselves, or implement custom 
geometry management functions.

For a subclass of VisClass to display itself on the screen, it must handle the 
message MSG_VIS_DRAW. This message is sent to all visible objects in a given 
window when that window is subjected to an exposure event. In addition, the 
object must be part of a tree of visible objects, the top node of which is 
connected to a GenView or other windowed object. Displaying a basic visible 
object is discussed in "Basic VisClass Rules" on page 1313 and "Drawing to 
the Screen" on page 1315.

For a visible object to handle mouse input, it will need to handle a subset of 
the mouse event messages. Typically, a visible object will want to know when 
the mouse is clicked within the object's bounds (MSG_META_START_SELECT) 
and when the mouse button is released (MSG_META_END_SELECT). Other 
messages dealing with mouse motion or other mouse buttons may also be of 
interest to the object. In addition, visible objects may request and handle Ink 
input. Handling of these messages is discussed in "Handling Input" on page 
1351.

Most applications using visible object trees will add objects to and remove 
them from the trees. MSG_VIS_ADD_CHILD and MSG_VIS_REMOVE are the 
two messages used most often for tree management. When an object should 
be freed, it can be destroyed with MSG_VIS_DESTROY, which will remove it 
from the tree and then free it.

Some applications will want to use the built-in geometry management 
features of GEOS. The geometry manager can automatically resize and 
reposition an entire visible object tree properly according to pre-set 
constraints. (The constraints can also be changed at run-time.) How the 
system manages visible object geometry is discussed in "Geometry 
Management" on page 1343.

The geometry manager, though extremely useful for non-overlapping objects, 
may not be sufficient for all the needs of a complex application. For an object 
to determine its own size and position, it has to handle some of the messages 
sent out by the geometry manager. You can also manually set the size and 
position of each visible object. This is discussed in "Positioning Visible 
Objects" on page 1338.

Often applications may need to change something about a visible object or 
the tree it's in. When this happens, the application must force a visual update 
by invalidating either the geometry or the image (or both) of the object and 
then calling MGS_VIS_VUP_UPDATE_WIN_GROUP. To mark any object 
invalid, the application must call MSG_VIS_MARK_INVALID.

Many visible objects will have specific functions they perform. For example, 
if the user presses on a menu item labeled "New Game" or something similar, 
the visible object may return itself to its original location (as in the TicTac 
sample application). To get this type of functionality, you must define new 
messages for your subclass of VisClass and have the object handle them. In 
the case of the TicTac game pieces, each piece handles the 
MSG_PIECE_NEW_GAME message by resetting the object's position to its 
original position.

Visible objects are maintained and managed in a tree structure. The tree has 
three basic elements: The root (topmost) node must be an object of 
VisContentClass. Any nodes in the middle of the tree, nodes that are 
allowed to have children, must be of VisCompClass. Any leaf nodes 
(guaranteed not to have children) may be of either VisClass or 
VisCompClass. (Subclasses of the above classes may also be used.)

The visible object tree is displayed normally through a GenView object. The 
output of the GenView must be tied directly to the top node of the visible 
object tree; this is why the visible tree must be headed by a VisContent-only 
the VisContent has the methods to handle GenView messages.

The VisContent object may or may not do things other than manage the 
visible tree. For example, the content may draw some background graphics 
to the window before the other visible objects draw themselves, or it may 
implement some special geometry behavior to arrange its children.

The VisContent can have children. These children can be either standard 
visible objects or composite visible objects. Composites, like the content, are 
allowed to have children. For efficiency, standard visible objects can not have 
children. Therefore, only leaf objects in the tree may be of VisClass.

The visible object tree may have any number of layers of composites. You 
should pay attention to the functions required in your application and fit the 
structure of the tree to the application's needs.

These restrictions, combined with the link to the generic object tree through 
GenView, result in an object tree structure somewhat like that shown in 
Figure 23-2. Of course, the actual generic and visible tree structure will vary 
from application to application. Also, note that the generic and visible 
sections are actually two different object trees; they are not connected 
through a parent-child relationship anywhere.

	23.4.2	Drawing to the Screen

One of the main features of visible objects is their ability to draw themselves 
on the screen. The visible tree does not have to detect when drawing or 
redrawing should be done; the UI will do this automatically through the 
window system and the GenView object.

	23.4.2.1	Visual Updates

MSG_VIS_OPEN, MSG_VIS_CLOSE

The visible tree will have to draw or redraw itself when a portion of its 
GenView window becomes newly exposed. The GenView keeps track of its 
window and will notify its content when any portion of the window becomes 
exposed. Exposure can occur from several events: The view window could be 
newly created; another window could have been moved, exposing the view's 
window; or the view window could have been scrolled.

Each of these exposure events looks exactly the same to the visible tree. 
When one of them occurs, the GenView will send a MSG_META_EXPOSED to 
its content object. The content (a VisContent or GenDocument if you're using 
a visible tree) will create a GState for the window and translate the 
MSG_META_EXPOSED into a MSG_VIS_DRAW. It will then send this 
MSG_VIS_DRAW to itself.

The default handler for MSG_VIS_DRAW in a composite is to simply pass the 
message on to all of the composite's children. There is no default behavior for 
MSG_VIS_DRAW in VisClass.

Any object (content, composite, or leaf) that wants to represent itself on the 
screen must handle MSG_VIS_DRAW. Any composite that subclasses this 
message must be sure to pass it on to all of its children with the following 
line:

@send @visChildren::MSG_VIS_DRAW(drawFlags, gstate);

Redrawing is not initiated only by the view window becoming exposed. It can 
also be initiated by some portion of the visible tree changing so that it needs 
to be redrawn (e.g., a child is moved from one composite to another, which 
may have an effect on the visual representation of the composite). Typically, 
any change that necessitates a redrawing will automatically generate a 
MSG_VIS_DRAW to the appropriate objects. These operations, however, will 
require a VisUpdateMode to be passed along with the other parameters.

All of the above assumes that the visible object is "open" or "realized." If an 
object is not open, it will not appear on the screen or as part of a composite's 
geometry calculations. When a window is first created, the window's content 
is automatically opened with MSG_VIS_OPEN. In the case of a visible tree 
attached to a GenView, this means that the VisContent object will be opened 
along with the window. All of the VisContent's children will also be opened 
automatically (assuming their VOF_WINDOW_INVALID bits are set, which is 
true the first time a visible object comes up).

If a visible object is added to an already-opened composite, the child will 
automatically be opened and marked invalid. This will cause the composite's 
geometry and image to be updated during the next visual update. If a child 
is added to a composite that is not currently open, the child will not be 
opened.

Although it is rarely done directly, you can manually open a visible object 
with the message MSG_VIS_OPEN, and you can "close" an object (remove it 
from the screen and from the tree's geometry calculations) with 
MSG_VIS_CLOSE. To open or close an entire branch of the visible tree, you can 
send the appropriate message to the top composite object in the branch. The 
message will propagate down through all the visible children.

n	MSG_VIS_OPEN

void	MSG_VIS_OPEN(

	WindowHandle window);

This message is part of the visual update mechanism and will be sent by the 
system when an object must be visually updated to appear on the screen. It 
will be sent to any VOF_WINDOW_INVALID objects in a branch whose 
VTF_IS_WIN_GROUP object has become VA_VISIBLE. Any object added into a 
visible tree having VOF_WINDOW_INVALID set will receive a MSG_VIS_OPEN 
at the next visual update. This message propagates down the visible tree and 
does not cross over boundaries of window groups. This message is often 
subclassed by objects that want to initialize some information before being 
drawn on the screen. If an object subclasses this message, it should be sure 
to call its superclass somewhere in the handler.

Source:	Visual update mechanism.

Destination:	Any visible object.

Parameters:	window	Handle of window in which the object is to appear, 
or zero if it should appear in the top window object.

Return:	Nothing.

Interception:	Will be intercepted by objects that want to initialize certain data or 
take certain actions before being drawn on the screen. Any intercepting 
objects must call the superclass somewhere in their handler.

n	MSG_VIS_CLOSE

void	MSG_VIS_CLOSE();

This message is part of the visual update mechanism and is sent to objects 
that are being taken off the screen. The system will send this message to any 
objects in a visual branch whose VTF_IS_WIN_GROUP object is set not visible 
(~VA_VISIBLE). This message closes appropriate windows and propagates to 
all children to the bottom leaf objects of the visible branch. This message will 
not cross window group boundaries; if a lower VTF_IS_WIN_GROUP object is 
encountered during the message propagation, an error will likely occur. 
Therefore, lower window groups must be closed before higher window groups 
may be closed.

Source:	Visual update mechanism.

Destination:	Any visible object.

Interception:	Will be intercepted by objects that want to do something as it is being 
taken off the screen. Any objects that intercept the message must call 
their superclasses in the handlers.

	23.4.2.2	VisUpdateMode

VisUpdateMode is an enumerated type that determines when and how the 
visible tree will be visually updated when its image or geometry becomes 
invalid. This type has four enumerations, described below:

VUM_MANUAL
This mode indicates that the UI should not update at all after 
this change. Instead, the visual update will be initiated 
manually later on.

VUM_NOW	This mode indicates that the visual update should occur 
immediately after the change is effected.

VUM_DELAYED_VIA_UI_QUEUE
This mode indicates that the visual update should occur only 
when the UI queue is completely empty (indicating no further 
changes are coming).

VUM_DELAYED_VIA_APP_QUEUE
This mode indicates that the visual update should occur only 
when the application's queue is empty (indicating that no more 
changes are coming). This mode is very useful for making 
several changes that each require an update; it will put the 
updating off until the very end and will cause only a single 
update.

A VisUpdateMode is passed as a parameter to certain Vis and Gen 
messages. These messages typically have some effect on the visual 
representation of the objects-either on the geometry or on the image itself.

	23.4.2.3	The Initial GState

MSG_VIS_VUP_CREATE_GSTATE

For any drawing to occur, a graphic state must exist. The graphic state 
typically is associated with the GenView's window and is created 
automatically, either when the window is first realized on the screen or when 
an exposure event occurs.

To create a GState, the system generates a MSG_VIS_VUP_CREATE_GSTATE 
and sends it to the object that first requires a visual update. This message 
travels up the visible tree until it gets to a window group (an object with its 
VTF_IS_WINDOW flag set), and then it creates a GState associated with that 
window object. Sometimes a content object will subclass this message to set 
up its own display information before the GenView window can create the 
new GState. The other time in which this message may be subclassed is by a 
content that manages a 32-bit graphics space; the content will have to 
translate the gstate to the proper position in the large document before 
letting other objects use it.

n	MSG_VIS_VUP_CREATE_GSTATE

GStateHandle MSG_VIS_VUP_CREATE_GSTATE();

This message travels up the visible object tree until it reaches either the root 
object or a window group object. It then creates a graphic state associated 
with that object; this graphic state is then used for the subsequent visual 
update. You may wish to subclass this message in order to alter the GState 
created or to set it up to take 32-bit coordinates. If you subclass it, however, 
be sure to call the superclass somewhere in the handler.

Source:	Unrestricted-typically sent by a visible object to itself.

Destination:	Any visible object-typically sent by a visible object to itself.

Parameters:	None.

Return:	The GStateHandle of the newly-created GState.

Interception:	Unlikely-VisContent objects may intercept this message to translate 
the returned GState in a 32-bit graphics space. In this case, the 
VisContent must first call its superclass, then translate the GState 
appropriately before returning.

	23.4.2.4	Retrieving the Current Window Handle

MSG_VIS_QUERY_WINDOW

Often a visible object will require the window handle of the window it's 
currently residing in. Some objects, for example, will want to force visual 
updates in real-time, and they can do this by using the current window 
handle, creating a special GState for it, and drawing to that GState. The 
visible object can either cache the window handle when the window is first 
opened, or it can retrieve it with MSG_VIS_QUERY_WINDOW.

n	MSG_VIS_QUERY_WINDOW

WindowHandle MSG_VIS_QUERY_WINDOW();

This message returns the window handle of the window the object currently 
resides in. In many cases, this will be the window handle of a GenView 
window.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself to retrieve 
its current window handle.

Parameters:	None.

Return:	The window handle of the object's current window.

Interception:	Unlikely.

See Also:	MSG_GEN_VIEW_GET_WINDOW.

	23.4.2.5	Causing Redrawing

MSG_VIS_BOUNDS_CHANGED, MSG_VIS_REDRAW_ENTIRE_OBJECT, 
MSG_VIS_INVALIDATE, MSG_VIS_MARK_INVALID, 
MSG_VIS_INVAL_TREE, MSG_VIS_VUP_ADD_RECT_TO_UPDATE_REGION

If your visible tree contains a composite that manages its own children, 
chances are you'll need to force a visual update after certain changes occur. 
For example, if you have an object that can be moved with the mouse, it will 
probably want to erase its image and redraw itself somewhere else after the 
move; since the geometry manager is not involved here, the object must force 
a redrawing of the affected portion of the visible tree.

There are several ways an object can force a redraw. These all take the form 
of messages, each of which is described below.

MSG_VIS_DRAW
This message causes the entire visible branch to draw itself. 
This message may be sent by any object to any other object, 
including itself. It does not, however, update the screen image; 
you must call MSG_VIS_VUP_UPDATE_WIN_GROUP.

MSG_VIS_BOUNDS_CHANGED
This message causes the visible object to mark the affected 
portions invalid, causing the visual update mechanism to 
redraw that portion during the next visual update. This 
message is part of the visible update mechanism.

MSG_VIS_REDRAW_ENTIRE_OBJECT
This message causes the visible object to redraw itself entirely 
(as opposed to just the invalid portion) if it is currently 
drawable. Essentially, the object will send itself a 
MSG_VIS_DRAW when it receives this message. This is 
especially useful if an object needs to completely change its 
image.

MSG_VIS_INVALIDATE
This message invalidates the entire region inside the visible 
object's bounds. It will cause the window system to generate a 
MSG_META_EXPOSED for the affected area, causing a 
MSG_VIS_DRAW to propagate down the tree to all affected 
objects. Note that this message must be subclassed to work 
with scaled windows or large documents.

MSG_VIS_INVAL_TREE
This message invalidates the entire region inside the visible 
object's bounds, including any child window areas. The window 
system will generate a MSG_META_EXPOSED for all affected 
windows.

MSG_VIS_MARK_INVALID
This message allows the caller to set an object's invalid flags so 
the object will be properly updated later. The object is marked 
as being invalid, and the default handler ensures a visual 
update path is created. This method may not be subclassed by 
applications.

MSG_VIS_VUP_ADD_RECT_TO_UPDATE_REGION
This message adds the passed rectangular region to a window's 
update list. Essentially, the window group associated with the 
recipient object will ensure that the given rectangle gets 
marked invalid and included in the next visual update.

n	MSG_VIS_DRAW

void	MSG_VIS_DRAW(

	DrawFlags		drawFlags,

	GStateHandle		gstate);

This message causes the visible object to draw itself. The default behavior of 
this message for composite objects is to pass the message on to all children. 
There is no default behavior for VisClass for this message.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	drawFlags	A record of type DrawFlags (defined below). The 
flags in this record describe what type of action 
initiated the MSG_VIS_DRAW.

gstate	The GStateHandle of the gstate created for this 
visual update. All drawing done in the handler 
should be for this GState.

Return:	Nothing.

Interception:	All visible objects that wish to draw anything to the screen must 
intercept this message. Composites that intercept it must be sure to 
send it to their children (with @send @visChildren).

Structures:	The flags in the DrawFlags record are listed below:

DF_EXPOSED	This flag indicates the MSG_VIS_DRAW is a result of 
a MSG_META_EXPOSED from the window system. 
This is the standard and most usual form of 
MSG_VIS_DRAW.

DF_OBJECT_SPECIFIC
This flag is used by various Specific UI objects for 
object-specific things. Your visible objects should 
not be concerned with this flag.

DF_PRINT	This flag indicates that the MSG_VIS_DRAW is a 
result of a MSG_META_EXPOSED_FOR_PRINT, the 
printing message. The GState passed will be a 
spooler GState rather than a window GState. If 
this flag is set, DF_EXPOSED will also be set.

DF_DONT_DRAW_CHILDREN
This flag indicates that composite objects should 
draw themselves but should not propagate the 
drawing message on to their children (this is 
nonstandard behavior).

DF_DISPLAY_TYPE	This is actually an enumerated type indicating the 
display type being used by the system right now. 
The display type enumeration is named 
DisplayClass. For review, the types are listed 
below:

	DC_TEXT, DC_GRAY_1, DC_GRAY_2, DC_GRAY_4, 
DC_GRAY_8, DC_COLOR_2, DC_COLOR_4, 
DC_CF_RGB.

n	MSG_VIS_BOUNDS_CHANGED

void	MSG_VIS_BOUNDS_CHANGED(@stack

	word	bottom,

	word	right,

	word	top,

	word	left);

The geometry manager sends this message when a geometry update changes 
an object's bounds.

Source:	Unrestricted-sent by the geometry manager when a visible object's 
bounds have changed as the result of a geometry change.

Destination:	Any visible object.

Parameters:	bottom, right, top, left
The four parameters correspond to the rectangle 
defining the object's old bounds. The parameters 
are passed on the stack.

Return:	Nothing.

Interception:	Unlikely. If the object subclasses this message, it should invalidate any 
part of its old bounds that it might have drawn in (the default handler 
invalidates the entire passed range).

n	MSG_VIS_REDRAW_ENTIRE_OBJECT

void	MSG_VIS_REDRAW_ENTIRE_OBJECT();

This message causes the object send itself a MSG_VIS_DRAW, creating and 
destroying a GState for itself.

Source:	Unrestricted-typically sent by an object to itself because of a state 
change, not as part of the visual update mechanism.

Destination:	Any visible object-typically sent by an object to itself.

Interception:	Unlikely.

n	MSG_VIS_INVALIDATE

void	MSG_VIS_INVALIDATE();

This message invalidates the entire region within the object's bounds. The 
message will cause the window system to generate a MSG_META_EXPOSED 
for the area covered by the bounds, causing a visual update to occur.

Source:	Unrestricted.

Destination:	Any visible object.

Interception:	Must be intercepted if the object is working in a 32-bit document space. 
Must also be intercepted to work with scaled views.

n	MSG_VIS_INVAL_TREE

void	MSG_VIS_INVAL_TREE();

This message has the effect of MSG_VIS_INVALIDATE on an entire branch of 
the visible tree. The window system will generate MSG_META_EXPOSED for 
each affected window.

Source:	Unrestricted.

Destination:	Any visible object.

Interception:	Unlikely.

n	MSG_VIS_MARK_INVALID

void	MSG_VIS_MARK_INVALID(

	VisOptFlags		flagsToSet,

	VisUpdateMode		updateMode);

This message allows the caller to set the recipient's VI_optFlags record so the 
object will get updated properly during the next visual update. The flags that 
can be set with this message are VOF_GEOMETRY_INVALID, 
VOF_WINDOW_INVALID, and VOF_IMAGE_INVALID. For more information 
on these flags, see section 23.3.4 on page 1306.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	flagsToSet	A record of VisOptFlags indicating which type of 
invalidation is being caused. The flags allowed with 
this message are VOF_GEOMETRY_INVALID, 
VOF_WINDOW_INVALID, and 
VOF_IMAGE_INVALID.

updateMode	A VisUpdateMode indicating when the visual 
update caused by this message should occur.

Return:	Nothing.

Interception:	May not be subclassed. Certain optimizations are made in the default 
handler, and subclassing may have unpredictable results.

n	MSG_VIS_ADD_RECT_TO_UPDATE_REGION

void	MSG_VIS_ADD_RECT_TO_UPDATE_REGION(@stack

	byte		unused,		/* for word alignment of parameters */

	VisAddRectFlags		addRectFlags,

	word		bottom,

	word		right,

	word		top,

	word		left);

This message adds the passed rectangular region to the window group's list 
of regions that require visual update. The handler for this message will 
ensure that the window group object for this branch of the tree marks the 
region as invalid so it will be included in the next visual update. The 
addRectFlags parameter contains either of the flags listed below.

Source:	Unrestricted-usually sent by an object to itself.

Destination:	Any visible object-usually sent by an object to itself.

Parameters:	unused	An unused byte for alignment of parameters.

addRectFlags	A record of VisAddRectFlags, defined below.

rectangle coords	The coordinates of the rectangle to be added to the 
invalidation region.

Return:	Nothing.

Interception:	Unlikely-a composite object may wish to optimize invalidation by 
altering the passed bounds and then passing the message on to its 
superclass.

Structures:	The VisAddRectFlags are listed below:

VARF_NOT_IF_ALREADY_INVALID
This flag indicates that the passed rectangle should not be 
invalidated if any visible object in the hierarchy going up to the 
window group object is marked invalid.

VARF_ONLY_REDRAW_MARGINS
This flag indicates that the object is invalidating old bounds 
and may indicate that the system can use a special 
optimization for invalidation.

	23.4.2.6	Updating Window Groups

MSG_VIS_VUP_UPDATE_WIN_GROUP, MSG_VIS_UPDATE_WIN_GROUP, 
MSG_VIS_UPDATE_WINDOWS_AND_IMAGE

A window group is an object that has window in which visible objects are 
displayed. Typically, you will not create your own window group objects, but 
you may need to notify a window group when it needs to be updated visually. 
To be a window group, an object has to have its VTF_IS_WINDOW or 
VTF_IS_PORTAL flag set in its VI_typeFlags field.

The window group is responsible for keeping track of the regions of its 
coordinate space that require visual updating. When a region or object gets 
invalidated, the window group remembers that it is invalid and makes sure 
it gets updated during the next visual update.

Any object can request that a visual update occur for the entire branch 
managed by a window group. It can use the three messages described in this 
section to request or force a visual update for the window group.

n	MSG_VIS_VUP_UPDATE_WIN_GROUP

Boolean	MSG_VIS_VUP_UPDATE_WIN_GROUP(

	VisUpdateMode updateMode);

This message travels up the visible tree from the recipient object to the first 
window group encountered; it will then cause that window group to go 
through a visible update by sending the window group object a 
MSG_VIS_UPDATE_WIN_GROUP, below.

Source:	Unrestricted.

Destination:	Any visible object residing in the window group that is to be updated.

Parameters:	updateMode	A VisUpdateMode indicating when the visual 
update should occur. VUM_MANUAL has the effect 
of a "no operation" because VUM_MANUAL does not 
cause visual updates.

Return:	True if the update mechanism was invoked; false if i was not.

Interception:	Not allowed.

Warnings:	You may not subclass this message.

n	MSG_VIS_UPDATE_WIN_GROUP

void	MSG_VIS_UPDATE_WIN_GROUP(

	VisUpdateMode updateMode);

This message may only be sent by a window group object to itself. It causes 
the window group to actually go through a visual update.

Source:	Visible update mechanism.

Destination:	The window group object that is to be updated.

Parameters:	updateMode	A VisUpdateMode indicating when the visual 
update should occur. This is the same as passed to 
MSG_VIS_VUP_UPDATE_WIN_GROUP.

Return:	Nothing.

Interception:	Not allowed.

Warnings:	You may not subclass this message.

n	MSG_VIS_UPDATE_WINDOWS_AND_IMAGE

void	MSG_VIS_UPDATE_WINDOWS_AND_IMAGE(

	VisUpdateImageFlags updateImageFlags);

This message is called by a window group during a visual update. It should 
not be sent or handled by anything other than a window group. It causes both 
the geometry and image of the affected branch of the visible tree to be 
updated, and it is used on branches which are already visually realized on 
the screen.

Source:	Visual update mechanism.

Destination:	A window group object.

Parameters:	updateImageFlags
This is a record of VisUpdateImageFlags that 
govern the visual update of the window group.

Return:	Nothing.

Interception:	Not allowed.

Structures:	The flags of VisUpdateImageFlags are listed below:

VUIF_ALREADY_INVALIDATED
An optimization flag to keep an already-invalid 
composite from invalidating all its children.

VUIF_SEND_TO_ALL_CHILDREN
A flag to ensure that all children get invalidated; it 
is used when the composite only updates its 
margins for optimization.

Warnings:	You may not subclass this message.

	23.4.2.7	Using Visual Monikers

MSG_VIS_DRAW_MONIKER, MSG_VIS_GET_MONIKER_POS, 
MSG_VIS_GET_MONIKER_SIZE, MSG_VIS_FIND_MONIKER, 
MSG_VIS_CREATE_VIS_MONIKER

Although visual monikers are typically used with generic objects (and are, in 
fact, documented in the GenClass chapter), you can display monikers with 
visible objects as well. The four messages discussed in this section can be 
used to draw a visible moniker, get information about a moniker, or locate a 
particular moniker in the visible object tree.

n	MSG_VIS_DRAW_MONIKER

void	MSG_VIS_DRAW_MONIKER(@stack

	DrawMonikerFlags		monikerFlags,

	ChunkHandle		visMoniker,

	word		textHeight,

	GStateHandle		gstate,

	word		yMaximum,

	word		xMaximum,

	word		yInset,

	word		xInset);

This message draws a visual moniker for the object. This message may be 
called by an object on itself in its MSG_VIS_DRAW handler.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	monikerFlags	A record of DrawMonikerFlags indicating how 
the moniker should be drawn. These flags are 
described below.

visMoniker	The chunk handle of the chunk containing the 
actual moniker to be drawn. This chunk must be in 
the same block as the object handling the message.

textHeight	A parameter used for optimization-if the caller 
knows the system text height, it should pass it 
here. If not, it should pass zero.

gstate	The handle of the GState to use when drawing the 
moniker. Typically, this is received by 
MSG_VIS_DRAW, which invokes this message.

yMaximum	The maximum bottom bound of the moniker if 
DMF_CLIP_TO_MAX_WIDTH is set in monikerFlags. 
Pass MAX_COORD to avoid clipping.

xMaximum	The maximum right bound of the moniker if 
DMF_CLIP_TO_MAX_WIDTH is set in monikerFlags. 
Pass MAX_COORD to avoid clipping.

yInset	The vertical inset at which to begin drawing the 
moniker, if left or right justified.

xInset	The horizontal inset at which to begin drawing the 
moniker, if top or bottom justified.

Return:	Nothing.

Interception:	Unlikely.

Structures:	The DrawMonikerFlags structure is defined as follows:

typedef ByteFlags DrawMonikerFlags;
#define DMF_UNDERLINE_ACCELERATOR						0x40
		/* Underlines accelerator key, if any */
#define DMF_CLIP_TO_MAX_WIDTH						0x20
		/* Clips the moniker to the xMaximum
		 * parameter */
#define DMF_NONE						0x10
		/* Set to draw the moniker at the
		 * current pen position (ignore the
		 * xInset and yInset parameters) */
#define DMF_Y_JUST_MASK						0x0c
#define DMF_X_JUST_MASK						0x03
		/* These are two bitfields that
		 * determine the justification.
		 * Their offsets are below; they
		 * are of type Justification. */
#define DMF_Y_JUST_OFFSET					2
#define DMF_X_JUST_OFFSET					0

n	MSG_VIS_GET_MONIKER_POS

XYValueAsDWord MSG_VIS_GET_MONIKER_POS(@stack

	DrawMonikerFlags		monikerFlags,

	ChunkHandle		visMoniker,

	word		textHeight,

	GStateHandle		gstate,

	word		yMaximum,

	word		xMaximum,

	word		yInset,

	word		xInset);

This message returns the position at which the moniker would appear if it 
were drawn with MSG_VIS_DRAW_MONIKER. The moniker is not actually 
drawn by this message.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	See MSG_VIS_DRAW_MONIKER above.

Return:	A dword value representing the horizontal and vertical positions where 
the moniker would be drawn if it were drawn with the passed 
parameters. The horizontal position is returned in the high word; the 
vertical position is returned in the low word. Use the DWORD_X and 
DWORD_Y macros to extract the x and y values. These macros can be 
found in the file graphics.h.

Interception:	Unlikely.

n	MSG_VIS_GET_MONIKER_SIZE

SizeAsDWord MSG_VIS_GET_MONIKER_SIZE(@stack

	DrawMonikerFlags		monikerFlags,

	ChunkHandle		visMoniker,

	word		textHeight,

	GStateHandle		gstate,

	word		yMaximum,

	word		xMaximum,

	word		yInset,

	word		xInset);

This message returns the size of the moniker specified by the parameters. 
The moniker is not drawn.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	See MSG_VIS_DRAW_MONIKER above.

Return:	A dword value representing the size of the moniker. The width of the 
moniker is returned in the high word; the height is returned in the low 
word. Use the macros DWORD_WIDTH and DWORD_HEIGHT, which can 
be found in the file visC.goh and also on page 1336.

Interception:	Unlikely.

n	MSG_VIS_FIND_MONIKER

optr	MSG_VIS_FIND_MONIKER(@stack

	VisMonikerSearchFlags			searchFlags,

	MemHandle			destBlock,

	ChunkHandle			monikerList,

	DisplayType			displayType);

This message locates the given visual moniker list and returns the optr of the 
moniker most appropriate for the passed display scheme.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	searchFlags	A record of VisMonikerSearchFlags (described 
below) indicating the attributes of the moniker that 
should be returned.

destBlock	Handle of the block into which the moniker chunk 
should be copied.

monikerList	Chunk handle of the chunk containing the moniker 
list to search. The moniker list must be in the same 
object block as the object handling the message.

displayType	The DisplayType of the moniker to be found (see 
below).

Interception:	Unlikely.

Structures:	The VisMonikerSearchFlags are listed below.

typedef WordFlags VisMonikerSearchFlags;
#define VMSF_STYLE					0xf000
	/* Four bits defining the preferred style of
	 * the moniker. These bits are of type
	 * VMStyle, which is defined below. */

#define VMSF_COPY_CHUNK					0x0400
	/* Set if the moniker should be copied into
	 * the block specified if not already in
	 * that block. */
#define VMSF_REPLACE_LIST					0x0200
	/* Set if the moniker list chunk containing
	 * the VisMoniker should be replaced. The
	 * chunk handle of the list will then point
	 * to the moniker rather than the list. */
#define VMSF_GSTRING					0x0100
	/* Set if a GString moniker is expected,
	 * clear if a text moniker is expected. */

	/* The remaining bits of this record are
	 * reserved for internal use. */

#define VMSF_STYLE_OFFSET 12

typedef ByteEnum VMStyle;
#define VMS_TEXT					0
			/* Normal text moniker */
#define VMS_ABBREV_TEXT					1
			/* short text abbreviation */
#define VMS_GRAPHIC_TEXT					2
			/* textual GString */
#define VMS_ICON					3
			/* normal GString moniker */
#define VMS_TOOL					4
			/* tool moniker, normally smaller
			 * than a standard moniker */

The DisplayType flags are listed below and can be found in win.h:

typedef ByteFlags DisplayType;
#define DT_DISP_SIZE						0xc0
		/* Two bits indicating the size of the
		 * display; a DisplaySize value, one of
		 * DS_TINY (CGA, or 256 x 320),
		 * DS_STANDARD (EGA, VGA, HGC, MCGA),
		 * DS_LARGE (800 x 600 SVGA), or
		 * DS_HUGE (huge screens). */
#define DT_DISP_ASPECT_RATIO						0x30
		/* Two bits indicating the aspect
		 * ratio of the screen; a value of
		 * DisplayAspectRatio, one of
		 * DAR_NORMAL (VGA or MCGA),
		 * DAR_SQUISHED (EGA or HGC), or
		 * DAR_VERY_SQUISHED (CGA) */
#define DT_DISP_CLASS						0x0f
		/* Four bits indicating the class of
		 * the display driver (or closest
		 * match); A DisplayClass value, one of
		 * DC_TEXT (char only, not implemented),
		 * DC_GRAY_1 (1 bit/pixel gray scale),
		 * DC_GRAY_2 (2 bit/pixel gray scale),
		 * DC_GRAY_4 (4 bit/pixel gray scale),
		 * DC_GRAY_8 (8 bit/pixel gray scale),
		 * DC_COLOR_2 (2 bit/pixel color index),
		 * DC_COLOR_4 (4 bit/pixel color index),
		 * DC_COLOR_8 (8 bit/pixel color index),
		 * DC_CF_RGB (color with RGB values) */

n	MSG_VIS_CREATE_VIS_MONIKER

ChunkHandle MSG_VIS_CREATE_VIS_MONIKER(@stack

	CreateVisMonikerFlags			flags,

	word			height,

	word			width

	word			length,

	VisMonikerDataType			dataType,

	VisMonikerSourceType			sourceType,

	dword			source);

This message creates a new chunk for a visual moniker within the recipient's 
object block. The new moniker can be created from an already existing visual 
moniker, a visual moniker list, a text string, a GString, or a token from the 
token database. The source may be defined by a far pointer, a global memory 
handle, or an optr. If the source is a text string or GString, a visual moniker 
structure will be created for the string. The newly-created chunk is marked 
dirty if the CVMF_DIRTY flag is passed.

If a moniker list is passed, the entire list will be copied into the destination 
object block. You must make sure that all the monikers in the list will still 
exist when the list is used.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	flags	A record of CreateVisMonikerFlags. Currently 
only one may be passed: CVMF_DIRTY, which 
indicates that the chunk should be marked dirty.

height	The height of the moniker.

width	The width of the moniker.

length	The length of the moniker, if a text string.

dataType	The type of moniker, an enumeration of the type 
VisMonikerDataType. This parameter 
determines the type of moniker to be created.

sourceType	The type of source used to create the new moniker, 
an enumeration of VisMonikerSourceType.

source	This parameter can be a pointer to the source, the 
global handle of the block containing the source, or 
an optr pointing to the chunk containing the 
source, depending on the value in sourceType.

Return:	The chunk handle of the new visual moniker. The visual moniker 
chunk resides in the object block of the object receiving the message. If 
the flag CVMF_DIRTY is passed, the chunk will be marked dirty.

Interception:	Unlikely-custom UI gadgets may intercept in some cases.

Structures:	VisMonikerSourceType and VisMonikerDataType are defined 
below. Both can be found in visC.goh.

typedef ByteEnum VisMonikerSourceType;
#define VMST_FPTR					0
		/* Source is referenced by a pointer.
		 * CVMF_source is a far pointer. */
#define VMST_OPTR					1
		/* Source is referenced by an optr.
		 * CVMF_source is an optr. */
#define VMST_HPTR					2
		/* Source is referenced by a combination
		 * memory handle and offset into the
		 * memory block (as opposed to an optr
		 * in which the low word is actually a
		 * chunk handle, not an offset). */

typedef ByteEnum VisMonikerDataType;
#define VMDT_NULL					0
		/* There is no source. Not valid for
		 * MSG_VIS_CREATE_VIS_MONIKER. */
#define VMDT_VIS_MONIKER					1
		/* Source is a complete VisMoniker
		 * structure. CVMF_length indicates the
		 * size of a complete VisMoniker
		 * structure; CVMF_width and
		 * CVMF_height are unused. */
#define VMDT_TEXT					2
		/* Source is a text string. If the
		 * string is null-terminated,
		 * CVMF_length should be zero.
		 * Otherwise, CVMF_length is the length
		 * of the string; A VisMoniker
		 * structure will be created for the
		 * string. CVMF_width and CVMF_height
		 * are unused. */
#define VMDT_GSTRING					3
		/* Source is a GString. If CVMF_length
		 * is zero, the GString length is
		 * determined by scanning for
		 * GR_END_STRING. Otherwise, CVMF_length
		 * indicates the length of the GString.
		 * CVMF_width and CVMF_height indicate
		 * the width and height of the GString.
		 * If either is zero, the dimension will
		 * be calculated by examining the
		 * string. A VisMoniker structure will
		 * be created for the GString. */
#define VMDT_TOKEN					4
		/* Source is a GeodeToken. CVMF_length,
		 * CVMF_width, and CVMF_height are
		 * unused. The destination must be able
		 * to use this data type because the
		 * specific UI must decide which moniker
		 * to choose from the token in the token
		 * database. */

n	DWORD_HEIGHT

word	DWORD_HEIGHT(val);

	dword	val;

This macro extracts the height from a SizeAsDWord structure (dword).

n	DWORD_WIDTH

word	DWORD_WIDTH(val);

	dword	val;

This macro extracts the width from a SizeAsDWord structure (dword).

n	MAKE_SIZE_DWORD

SizeAsDWord MAKE_SIZE_DWORD(width, height);

	word	width, height;

This macro takes a width and height and creates a SizeAsDWord value.

	23.4.2.8	Cached GStates

MSG_VIS_CREATE_CACHED_GSTATES, 
MSG_VIS_RECREATE_CACHED_GSTATES, 
MSG_VIS_DESTROY_CACHED_GSTATES

Many complex visible objects (such as VisText and VisSpline) have both a 
cached GState and a reference count. When the reference count goes from 
zero to one, the Vis object creates and caches a GState; when the reference 
count goes from one to zero, the cached GState is destroyed. VisClass has 
three messages to create, update, and destroy the cached GStates. None of 
these messages has any default behavior; they are provided for complex 
objects to handle should they need them.

n	MSG_VIS_CREATE_CACHED_GSTATES

void	MSG_VIS_CREATE_CACHED_GSTATES();

This message may be used to create and cache a GState, typically to avoid 
having a complex Vis object update several times for several simple 
operations (such as pointer events).

Source:	Unrestricted.

Destination:	Any visible object.

Interception:	Must be intercepted to have any effect; there is no default behavior.

n	MSG_VIS_RECREATE_CACHED_GSTATES

void	MSG_VIS_RECREATE_CACHED_GSTATES();

This message may be used to have the Vis object destroy and recreate any 
cached GStates it has. For example, cached GStates of a complex visible 
object that gets moved or resized will no longer map to the proper place in the 
object's document. After the move or resize, this message may be used to 
update those GStates.

Source:	Unrestricted.

Destination:	Any visible object.

Interception:	Must be intercepted to have any effect; there is no default behavior.

n	MSG_VIS_DESTROY_CACHED_GSTATES

void	MSG_VIS_DESTROY_CACHED_GSTATES();

This message may be used to destroy any cached GStates the visible object 
may have.

Source:	Unrestricted.

Destination:	Any visible object.

Interception:	Must be intercepted to have any effect; there is no default behavior.

	23.4.3	Positioning Visible Objects

Every visible object has an instance data field called VI_bounds that records 
the object's visible bounds. Visible bounds are the left, top, right, and bottom 
bounds of a rectangle that define the maximum area covered by the visible 
object. The bounds are used primarily for determining the object's size and 
location.

The VI_bounds field is a Rectangle structure, provided by the graphics 
system. This structure has four components, as shown below:

typedef struct {
    sword   R_left;    /* x of upper-left corner */
    sword   R_top;     /* y of upper-left corner */
    sword   R_right;   /* x of lower-right corner */
    sword   R_bottom;  /* y of lower-right corner */
} Rectangle;

The bounds of non-window objects are stored in document coordinates 
relative to the document displayed by the window in which they appear. The 
left and top bounds constitute the position of the object. The difference 
between the right and left bounds is the object's width; the difference 
between bottom and top is its height. Together, the width and height 
constitute the object's size.

The bounds of a window or portal object (VTF_IS_WINDOW or 
VTF_IS_PORTAL) represent the location of the window, in document 
coordinates, within its parent window. The coordinate system within the 
window object is independent from that of its parent.

Unless an object's bounds are set in the Goc code, they will be set at zero and 
must be initialized to some values before the object can be drawn. This 
initialization can be done with the messages that set position and size, or it 
can be done automatically by the geometry manager (if a composite is 
managing its children).

The VI_bounds instance field exists in VisClass and therefore occurs also in 
VisCompClass and VisContentClass and all their subclasses. Any object 
can directly set any or all of its bounds; other objects (such as a parent 
VisComp) can direct the object to set its bounds to certain coordinates as a 
result of either geometry management or some user action. For example, a 
VisComp that has ten children may recalculate their positions if one of those 
children gets resized; the composite must then notify all the children of their 
new positions. To learn how a composite object can manage its children in 
different ways, see "VisComp," Chapter 24.

	23.4.3.1	Object Position and Bounds

MSG_VIS_GET_POSITION, MSG_VIS_SET_POSITION, 
MSG_VIS_GET_BOUNDS

An object's bounds determine both the location and the size of the object in 
the document space. The object may reposition itself or resize itself at will; 
for example, it may allow the user to move or resize it with the mouse. The 
object can also receive direction from other objects that it should change its 
bounds. Note that none of these messages by themselves will cause the object 
to redraw; you must also send a MSG_VIS_MARK_INVALID to the object to get 
either its geometry or its image to be marked invalid.

An object's position is represented by the upper-left corner of its bounds, 
defined by VI_bounds.R_top and VI_bounds.R_left. You can retrieve an 
object's position by sending it MSG_VIS_GET_POSITION, or you can set it with 
MSG_VIS_SET_POSITION. You can also use MSG_VIS_GET_BOUNDS to get all 
four components of the object's bounds.

An object can access its own bounds field with a simple pointer. Since every 
message has pself as an implicit parameter (a pointer to the object's instance 
data structure), any object can look at or change its bounds directly. (See the 
example in Code Display 23-2 on page u 1358.)

Using Swat, you can see a visible object's bounds with the command pobj.

If you have a composite object managing several children, you can arrange to 
have their positions determined automatically. This is discussed in section 
23.4.3.3 on page 1343.

n	MSG_VIS_SET_POSITION



void	MSG_VIS_SET_POSITION(

	int	xOrigin,

	int	yOrigin);

This message causes the object to set its VI_bounds to the new location 
specified, retaining its current size. The left bound (VI_bounds.R_left) is set 
to the value of xOrigin, and the top bound (VI_bounds.R_top) is set to that of 
yOrigin. The right and bottom bounds are set to match the new origin and 
the width and height of the object.

Source:	Unrestricted-usually the visible parent or geometry manager.

Destination:	Any visible object.

Parameters:	xOrigin	New horizontal coordinate of the object's position.

yOrigin	New vertical coordinate of the object's position.

Return:	Nothing.

Interception:	Unlikely. It's much more likely that the object will subclass 
MSG_VIS_POSITION_BRANCH.

Warnings:	This message will not cause an image invalidation. You must mark the 
object invalid with MSG_VIS_MARK_INVALID.

See Also:	MSG_VIS_POSITION_BRANCH, MSG_VIS_MARK_INVALID.

n	MSG_VIS_GET_POSITION



XYValueAsDWord MSG_VIS_GET_POSITION();

This message returns the current origin of the object. The origin returned 
consists of the left and top object bounds (VI_bounds.R_left and 
VI_bounds.R_top, respectively).

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	None.

Return:	A dword value representing the left bound in the low word and the top 
bound in the high word. Use the macros DWORD_X and DWORD_Y to 
extract the bounds from the return value (see the file graphics.h).s

Interception:	Unlikely.

n	MSG_VIS_GET_BOUNDS



void	MSG_VIS_GET_BOUNDS(

	Rectangle *retValue);

This message returns the current rectangle structure stored in the object's 
VI_bounds field. This rectangle represents both the position and the size of 
the object by giving its left, top, right, and bottom bounds.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	retValue	A pointer to an empty Rectangle structure. The 
values in the object's VI_bounds field will be 
returned in the structure pointed to.

Return:	The retValue pointer will be returned with the bounds filled into the 
Rectangle structure.

Interception:	Unlikely.

	23.4.3.2	Object Size

MSG_VIS_GET_SIZE, MSG_VIS_SET_SIZE

A visible object's size is defined as its width and height. The width is the 
difference between the object's left and right bounds; the height is the 
difference between the object's top and bottom bounds.

You can retrieve a visible object's size with the message MSG_VIS_GET_SIZE, 
and you can set it with MSG_VIS_SET_SIZE. MSG_VIS_SET_SIZE will set the 
object's right and bottom bounds without recalculating the object's position. 
If geometry is being managed automatically, you may want to subclass other 
messages; these are described in "Geometry Management" on page 1343.

In Swat, you can see the object's size indirectly with the command pobj. This 
command will show, among other things, the VI_bounds field of the object. 
You can manually calculate the size from that information.

n	MSG_VIS_SET_SIZE



void	MSG_VIS_SET_SIZE(

	int	width,

	int	height);

This message sets the object's height and width to the passed values, 
retaining the object's current position. The object's position will not be 
recalculated as a result of the size change. 

Source:	Unrestricted-usually the geometry manager or the object's visible 
parent calculating geometry.

Destination:	Any visible object.

Parameters:	width	The new width of the object. width will be added to 
the object's left bound to get the object's new right 
bound.

height	The new height of the object. height will be added 
to the object's top bound to get the object's new 
bottom bound.

Return:	Nothing.

Interception:	Unlikely.

Warnings:	This message will not cause an image invalidation. You must mark the 
object invalid with MSG_VIS_MARK_INVALID.

n	MSG_VIS_GET_SIZE



SizeAsDWord MSG_VIS_GET_SIZE();

This message returns the current size (width and height) of the object. Both 
values are word-sized integers and are returned in a single dword value. The 
high word of this value is the object's width, and the low word is the object's 
height.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	None.

Return:	A dword value representing the object's width in the low word and 
height in the high word. Use the macros DWORD_WIDTH and 
DWORD_HEIGHT to extract the width and height; see page 1336.

Interception:	Unlikely.

	23.4.3.3	Geometry Management

MSG_VIS_UPDATE_GEOMETRY, MSG_VIS_NOTIFY_GEOMETRY_VALID, 
MSG_VIS_RECALC_SIZE, MSG_VIS_GET_CENTER, 
MSG_VIS_RECALC_SIZE_AND_INVAL_IF_NEEDED, 
MSG_VIS_RESET_TO_INITIAL_SIZE, MSG_VIS_POSITION_BRANCH, 
MSG_VIS_POSITION_AND_INVAL_IF_NEEDED, 
MSG_VIS_INVAL_ALL_GEOMETRY

Geometry management consists of positioning and sizing visible objects 
properly. This can be done manually by the programmer or automatically by 
GEOS. If you wish to manually control your visible tree's geometry, set the 
flag VCGA_CUSTOM_MANAGE_CHILDREN in the top composite's 
VCI_geoAttrs field (see "VisComp," Chapter 24). You can then use any 
messages, either native to VisClass or defined by your subclasses, for object 
positioning and sizing.

Automatic geometry management occurs when the geometry of the visible 
tree is marked invalid somewhere and a visual update is initiated. The tree's 
geometry can be marked invalid in several ways-an object can be added to 
or removed from the tree, an object can be manually marked invalid (with 
MSG_VIS_MARK_INVALID), or an object can be opened or closed 
(MSG_VIS_OPEN or MSG_VIS_CLOSE).

When automatic geometry management is invoked, the geometry manager 
will recalculate the entire affected branch's geometry. It will calculate 
geometry for each affected window group, from the topmost affected window 
object down to the bottommost affected object. If the geometry manager 
encounters window groups below the topmost window, it will check first to 
see if the lower window's size is controlled by its children (e.g., a GenView 
that follows the geometry of its content). If the lower window is scrollable or 
otherwise not subject to its children's geometry, the geometry manager will 
finish calculating the geometry above the lower window before proceeding.

Calculating geometry is an involved, complex task. The process involves 
composites and their children negotiating on desired sizes. How the geometry 
is calculated depends primarily on the relationships between the objects and 
how their flags are set.

For example, if a GenView is set up to be exactly the same size as its 
VisContent object, the calculations will be different than if the GenView were 
scrollable. The same is true for visible composites that manage their 
children: If the composite resizes itself large enough to hold all its children, 
the children must be resized first.

The negotiation between parent and child in the visible tree takes the form 
of a single message: MSG_VIS_RECALC_SIZE. This is the single most 
important message in calculating the tree's geometry, though others are also 
significant. This message is sent by a composite to each of its children in turn; 
it passes a suggested size, and the child returns its desired size.

The composite collects all the desired sizes of its children and compares that 
to the size it thinks it should be. If necessary, it makes another pass through 
the children, or it passes on its desired size to its parent composite. 
Depending on the situation and the disparity between parent and children 
sizes, the geometry calculation may take a single pass or several. If the sizes 
can not be resolved through this negotiation, the geometry manager will 
make a decision after several passes, typically expanding the parent as much 
as possible to fit all the children.

After a visible object has calculated its size, its size will be set either by itself 
or by its parent. Often this is done with MSG_VIS_SET_SIZE. Once all sizes 
have been determined and set, the objects set their positions with 
MSG_VIS_POSITION_BRANCH, which propagates down the tree. It sets the 
position of the topmost composite and then sets each of its children's 
positions appropriately.

When geometry calculations are complete, the geometry manager will send a 
MSG_VIS_NOTIFY_GEOMETRY_VALID to all visible objects with the flag 
VGA_NOTIFY_GEOMETRY_VALID set in its VI_geoAttrs field.

Several other messages may be used during geometry updates. Some of them 
may be intercepted to alter the behavior of the default method. These 
messages are listed below. Others can be used to invalidate a visible object's 
geometry or to cause a geometry update on the tree.

MSG_VIS_UPDATE_GEOMETRY
This message is typically called by the UI during a window 
group update. It calculates the geometry of the entire branch 
receiving it. It's not likely you'll subclass this method-altering 
its behavior can be used for certain optimizations, however.

MSG_VIS_NOTIFY_GEOMETRY_VALID
This message will be sent to an object when all its geometry 
messages have been handled and its geometry has been fully 
resolved (at least for the moment). This message will be sent 
only if VGA_NOTIFY_GEOMETRY_VALID is set in the object's 
VI_geoAttrs field. There is no default behavior for this message; 
it should be intercepted only if the object needs to do 
calculations after the geometry has settled down.

MSG_VIS_RECALC_SIZE
This message is normally sent by the geometry manager to a 
composite object. The composite is expected to send it to all its 
children; the children will then determine their sizes, and the 
composite will figure the total size and return. A composite that 
manages its own children can also use this message to query its 
children for their desired sizes.

MSG_VIS_RECALC_SIZE_AND_INVAL_IF_NEEDED
This message is an optimized MSG_VIS_RECALC_SIZE. 
Composites should use this version when sending a 
recalculation message to their children. This message only 
causes recalculation if needed and will invalidate the object if 
the size gets recalculated. It invalidates the object's image at 
its old bounds and only invalidates its geometry if the bounds 
change. It is highly unlikely that you'll subclass this method.

MSG_VIS_GET_CENTER
This message returns the amount of space on each side the 
object wants reserved for itself. It does not, as the name 
suggests, return the coordinates of the object's center. Instead, 
it returns the distance in each direction the object requires (you 
may think of it as external margins).

MSG_VIS_RESET_TO_INITIAL_SIZE
This message propagates down the visible tree and causes 
every object that receives it to reset itself to its original size. It 
does this by clearing VGA_GEOMETRY_CALCULATED in the 
object's VI_geoAttrs field, causing the object to believe it is being 
put on-screen for the first time. This message will also set the 
object's flags to indicate that its geometry has become invalid. 
It's highly unlikely your application will subclass this method.

MSG_VIS_POSITION_BRANCH
This message is sent by the geometry manager when an entire 
visible branch should be repositioned. If an application wants 
to do something special, it should subclass the handler for this 
message. Typically, though, only subclasses of VisCompClass 
and perhaps VisContentClass will change this method.

MSG_VIS_POSITION_AND_INVAL_IF_NEEDED
This message is an optimized MSG_VIS_POSITION_BRANCH 
that causes a branch reposition only if it's necessary. It will also 
invalidate both the object's and the parent's original images 
and, if the position changes, the geometry as well. It is highly 
unlikely that you'll subclass this method.

MSG_VIS_INVAL_ALL_GEOMETRY
This message invalidates all geometry under the recipient 
object, forcing invalidation of all children. This is a brute-force 
message used only when absolutely necessary.

n	MSG_VIS_UPDATE_GEOMETRY

void	MSG_VIS_UPDATE_GEOMETRY();

This message is sent during a visual update to cause objects to recalculate 
their geometry. Applications can use this message to ensure that geometry 
gets updated for a visual branch even if the branch is not currently drawn on 
the screen.

Source:	Visual update mechanism.

Destination:	Any visible object.

Interception:	May be intercepted for optimizations. A thorough knowledge of the 
geometry update mechanism and the specifics of the visible tree's 
geometry is strongly recommended, however.

n	MSG_VIS_NOTIFY_GEOMETRY_VALID

void	MSG_VIS_NOTIFY_GEOMETRY_VALID();

This message is sent by the geometry manager to objects that have 
VGA_NOTIFY_GEOMETRY_VALID set. The message is sent only after all 
geometry messages have been handled for the object. It has no default 
behavior.

Source:	Visible update mechanism.

Destination:	Any visible object-typically a child of the object sending the message.

Interception:	This message has no default behavior. It should be intercepted by any 
object that needs to do something after its geometry has been made 
valid.

n	MSG_VIS_RECALC_SIZE

SizeAsDWord MSG_VIS_RECALC_SIZE(

	int	width,

	int	height);

This message takes the suggested height and width of the object and 
recalculates the object's desired size based on them. Composite objects are 
expected to pass this message to their children and then calculate their sizes 
based on those of their children. The default behavior of the handler for this 
is to return the current size no matter what the suggested size is.

Source:	Visible update mechanism.

Destination:	Any visible object.

Parameters:	width	Suggested new width of the object as determined by 
the object's parent.

height	Suggested new height of the object as determined 
by the object's parent.

Return:	A dword value representing the object's desired size as calculated by 
the object. The high word of the return value represents the width and 
the low word the height. Use the macros DWORD_WIDTH and 
DWORD_HEIGHT to extract the width and height; see page 1336.

Interception:	Default behavior is to return the object's current size no matter what 
the passed width and height are. Any object that wants special sizing 
behavior based either on the object's children or on the suggested size 
should subclass the method.

n	MSG_VIS_RECALC_SIZE_AND_INVAL_IF_NEEDED

SizeAsDWord MSG_VIS_RECALC_SIZE_AND_INVAL_IF_NEEDED(

	int	width,

	int	height);

This message is the same as MSG_VIS_CALC_RESIZE except that it is 
somewhat optimized. It will recalculate only if certain flags are set for the 
object, and it will mark the geometry invalid only if recalculation is done.

Source:	Visible update mechanism.

Destination:	Any visible object.

Parameters:	width	Suggested new width of the object as determined by 
the object's parent.

height	Suggested new height of the object as determined 
by the object's parent.

Return:	A dword value representing the object's desired size as calculated by 
the object. The low word of the return value represents the width and 
the high word the height.

Interception:	Unlikely-Default behavior is to return the object's current size no 
matter what the passed width and height are. Any object that wants 
special sizing behavior based either on the object's children or on the 
suggested size should subclass the method.

n	MSG_VIS_GET_CENTER



void	MSG_VIS_GET_CENTER(

	GetCenterParams *retValue);

This message returns the amount of space needed by the object in each 
direction from its center. It does not, as the name suggests, return the 
coordinates of the center of the object. Instead, the object must determine the 
amount of space it requires from its center to each edge for geometry 
management and return them in the structure passed.

Source:	Visible update mechanism.

Destination:	Any visible object

Parameters:	retValue	A pointer to an empty GetCenterParams 
structure, defined below.

Return:	The method must fill the GetCenterParams structure pointed to by 
the retValue parameter.

Interception:	Any object that wants to effect a different centering than the default 
should subclass this method. For example, if a set of objects can be 
overlapped, or if they should have extra space between them, they 
should subclass this message and alter the returned values 
appropriately.

Structures:	The GetCenterParams structure is defined as follows:

typedef struct {
    word   GCP_aboveCenter;    /* space above */
    word   GCP_belowCenter;    /* space below */
    word   GCP_leftOfCenter;   /* space left */
    word   GCP_rightOfCenter;  /* space right */
} GetCenterParams;

n	MSG_VIS_RESET_TO_INITIAL_SIZE

void	MSG_VIS_RESET_TO_INITIAL_SIZE(

	VisUpdateMode updateMode);

This message propagates down an entire visual branch, causing the objects 
in it to reset their sizes to their original width and height. First it invalidates 
the object's geometry, then it recalculates the geometry starting at the top.

Source:	Visible update mechanism.

Destination:	Any visible object.

Parameters:	updateMode	A VisUpdateMode indicating when the visual 
update of the tree should occur.

Return:	Nothing.

Interception:	Unlikely.

n	MSG_VIS_POSITION_BRANCH

void	MSG_VIS_POSITION_BRANCH(

	word	xOrigin,

	word	yOrigin);

This message repositions an entire visible branch. It propagates down the 
branch, causing each visible object to reposition itself based on the new 
origins passed. Composites must pass the appropriate altered positions to 
their children.

Source:	Visible update mechanism.

Destination:	Any visible object.

Parameters:	xOrigin	The new horizontal position of the object relative to 
the document or window it's in. This value is set 
into the object's VI_bounds.R_left bound, and the 
right bound is set according to the object's size.

yOrigin	The new vertical position of the object relative to 
the document or window it's in. This value is set 
into the object's VI_bounds.R_top bound, and the 
bottom bound is set according to the object's size.

Return:	Nothing.

Interception:	The default behavior is to set the object to the passed position. 
Composite objects that want to position their children a special way 
should subclass this (and not call the superclass) method. 
Non-composites will rarely, if ever, subclass this message.

n	MSG_VIS_POSITION_AND_INVAL_IF_NEEDED

Boolean	MSG_VIS_POSITION_AND_INVAL_IF_NEEDED(

	word	xPosition,

	word	yPosition);

This message is an optimized version of MSG_VIS_POSITION_BRANCH. It 
repositions the branch only if necessary and will mark the image invalid only 
if the position was changed. It returns a flag indicating whether or not the 
object was repositioned.

Source:	Visible update mechanism.

Destination:	Any visible object-typically sent by a composite to its children.

Parameters:	xPosition	The new horizontal position of the object relative to 
the document or window it's in.

yPosition	The new vertical position of the object relative to 
the document or window it's in.

Return:	If the object was repositioned, the message will return true. Otherwise, 
it will return false.

Interception:	Unlikely.

n	MSG_VIS_INVAL_ALL_GEOMETRY

void	MSG_VIS_INVAL_ALL_GEOMETRY(

	VisUpdateMode		updateMode);

This is a brute-force, desperation message used to invalidate all geometry in 
the recipient's tree; that is, all geometry of the recipient and all objects under 
it in the tree will be invalidated. You should only use this message when the 
whole tree should be recalculated.

Source:	Unrestricted.

Destination:	The object requiring geometry recalculation.

Parameters:	updateMode	A visual update mode indicating when the visual 
update of the recalculation should occur.

Return:	Nothing.

Interception:	Generally not intercepted.

	23.4.4	Handling Input

Input events, what they mean, and how they are generated are discussed 
fully in "Input," Chapter 11 of the Concepts Book. The visible world has some 
default behavior for handling input messages such as 
MSG_META_START_SELECT, MSG_META_END_SELECT, and 
MSG_META_PTR. For the most part, however, visible objects that want to 
respond to input must subclass and handle the input messages that interest 
them.

Composite objects will automatically pass mouse messages on to the proper 
child directly under the mouse pointer. Non-composite objects (direct 
subclasses of VisClass) have no special default behavior for input handling.

Note that VisClass does not intelligently handle layering of objects. That is, 
if one object is visibly on top of another object, it will not necessarily receive 
the input events-the events may be passed to the partially hidden object. 
This is due to the order in which drawing and mouse events are handled by 
a visible object's children.

Take the example of a visible composite with two children. Each child draws 
a filled rectangle covering its bounds; the first child has a width and height 
of 40, and the second child has a width and height of 20. The composite's 
declaration shows

    ...
    VCI_comp = LargeChild, SmallChild;

    ...

Because drawing occurs in the order the children are listed, the small child 
will be drawn over the large child, as in Figure 23-3. If each object can 
intercept and handle mouse events (e.g., MSG_META_START_SELECT), clicks 
will never reach the small object without special behavior added to the 
composite. This is because input events are handled in the same order as 
drawing; the input event will be given to the first child whose bounds include 
the event's coordinates.

So, a click event on (10, 10), which is in the middle of the small square, would 
first be passed to the LargeChild object. The large child would see that the 
click was within its bounds, and it would take the event. The event would 
never be handled by the small object.

Therefore, if you need to have overlapping objects which handle user input, 
you will have to add special features for bounds detection. In the example of 
the two squares, if neither were to move, the composite could simply pass the 
event to the small child first and then to the large child, assuming the small 
child is always on top. If the objects could be moved forward and back so they 
hide each other, the composite (or the objects themselves) will need some 
other, more complex, detection behavior.

	23.4.4.1	Mouse Events

MSG_META_PTR, MSG_META_START_SELECT, MSG_META_END_SELECT, 
MSG_META_DRAG_SELECT, MSG_META_DRAG, 
MSG_META_START_MOVE_COPY, MSG_META_DRAG_MOVE_COPY, 
MSG_META_START_OTHER, MSG_META_END_OTHER, 
MSG_META_DRAG_OTHER

Composite objects will automatically pass mouse messages on to the first 
child directly under the mouse pointer. Non-composite objects (direct 
subclasses of VisClass) have no special default behavior for input handling.

Typically, a visible object that needs to handle mouse input will subclass 
MSG_META_START_SELECT (or one of the other press events such as 
MSG_META_START_MOVE_COPY). This message is sent when the user 
presses on the "select" mouse button while the pointer is over the object. In 
this method, the object should grab the mouse (as shown below). When it has 
the mouse grab, it will receive MSG_META_PTR each time the mouse is 
moved; the object should subclass this message to provide the desired 
reaction to mouse moves. Finally, when the user releases the select button, 
the object will receive a MSG_META_END_SELECT. At this point, it should 
release the mouse grab.

Typically, mouse events will arrive with coordinates specified in 16 bits. This 
is the default graphics space, and it represents a coordinate system more 
than 25 yards on a side. Nearly all applications will find this graphic system 
big enough for their uses. However, if you need larger coordinates, you can 
use the large document space with 32-bit coordinates. To do this, you must 
set the GVA_WINDOW_COORDINATE_MOUSE_EVENTS in the GVI_attrs field 
of your GenView object and set up your visible objects correctly. For more 
information on supporting 32-bit graphic spaces with visible objects, see 
"Visible Layers and 32-Bit Graphics" on page 1393.

		Grabbing the Mouse

MSG_VIS_GRAB_MOUSE, MSG_VIS_FORCE_GRAB_MOUSE, 
MSG_VIS_GRAB_LARGE_MOUSE, MSG_VIS_FORCE_GRAB_LARGE_MOUSE, 
MSG_VIS_RELEASE_MOUSE

When an object "grabs the mouse," it requests that the UI send all future 
mouse events directly to that object. Normally, mouse events will travel down 
the visible object tree until they reach either the leaf object under the pointer 
or an object under the pointer that handles them. When an object has the 
mouse grab, the mouse events will go to the object with the grab regardless 
of the location of the pointer.

Typically, if an object wants to receive mouse events, it will subclass 
MSG_META_START_SELECT. This message is sent to the object when the 
pointer is over the object's bounds and the user presses the select button. In 
this handler, the object grabs the UI's gadget exclusive and then grabs the 
mouse. A good example of this can be found in the TicTac sample application's 
handler for MSG_META_START_SELECT.

After an object grabs the mouse, it receives all pointer and drag events that 
occur. These are primarily MSG_META_PTR messages, and the object must 
subclass MSG_META_PTR to achieve the proper behavior it wants. When the 
user lets go of the select button, the object will receive a 
MSG_META_END_SELECT. If it grabbed the mouse (which it probably did if it 
receives this message), it must relinquish both the gadget exclusive and its 
mouse grab.

An example of getting and releasing the mouse grab (taken from the TicTac 
sample application) is shown in Code Display 23-2. The object subclasses 
these messages to let the user drag it around the screen.

The UI allows the visible object to get the normal mouse grab by using four 
different messages. Each of these is detailed below. If you're using a large 
document (32-bit coordinates), you will use the "large" mouse grabs. 
Otherwise, the normal mouse grab messages will do.

n	MSG_VIS_GRAB_MOUSE

void	MSG_VIS_GRAB_MOUSE();

A visible object sends itself this message (with @call) when it wants to 
acquire the normal mouse grab. The message MSG_VIS_RELEASE_MOUSE 
must be used to relinquish the grab.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by the object to itself.

Interception:	Highly unlikely.

n	MSG_VIS_FORCE_GRAB_MOUSE

void	MSG_VIS_FORCE_GRAB_MOUSE();

A visible object sends itself this message (with @call) when it wants to 
forcibly grab the mouse input. The object will acquire the mouse grab even if 
another object currently has it; the other object will receive a 
MSG_VIS_LOST_GADGET_EXCL when it loses the mouse by a forced grab. The 
object must release the grab later with MSG_VIS_RELEASE_MOUSE.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by the object to itself.

Interception:	Highly unlikely.

n	MSG_VIS_GRAB_LARGE_MOUSE

void	MSG_VIS_GRAB_LARGE_MOUSE();

A visible object sends itself this message (with @call) when it wants to 
acquire the mouse grab and when it wants 32-bit coordinates. If the object 
wants 16-bit coordinates, it should use MSG_VIS_GRAB_MOUSE, above. The 
object must relinquish the mouse grab with MSG_VIS_RELEASE_MOUSE.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by the object to itself.

Interception:	Highly unlikely.

n	MSG_VIS_FORCE_GRAB_LARGE_MOUSE

void	MSG_VIS_FORCE_GRAB_LARGE_MOUSE();

A visible object sends itself this message (with @call) when it wants to 
forcibly grab the mouse input and when it wants large (32-bit) input 
coordinates. If it wants normal (16-bit) coordinates, it should use 
MSG_VIS_FORCE_GRAB_MOUSE, above. The object will acquire the mouse 
grab even if another object currently has it; the other object will receive a 
MSG_VIS_LOST_GADGET_EXCL when it loses the mouse by a forced grab. The 
object must release the grab later with MSG_VIS_RELEASE_MOUSE.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by the object to itself.

Interception:	Highly unlikely.

n	MSG_VIS_VUP_ALTER_INPUT_FLOW

void	MSG_VIS_VUP_ALTER_INPUT_FLOW(@stack

	PointDWord		translation,

	WindowHandle		window,

	optr		object,

	word		grapTypeAndFlags);

This message is the primitive employed by the grab/release messages shown 
above. Objects will rarely use this unless they are large objects (using 32-bit 
coordinates). Large objects and composites should subclass this message. In 
the case of a mouse grab, they should add in their 32-bit offset amounts to the 
translation structure before passing the event on to their superclasses. This 
will result in large mouse events being properly translated for the duration 
of the mouse grab.

Source:	Unrestricted.

Destination:	Any visible object-typically a VisContent which uses a 32-bit graphics 
space for its children.

Parameters:	translation	The offsets to the origin of the "local" 16-bit 
graphics space.

window	The handle of the view window associated with this 
input flow alteration.

object	The optr of the object altering the input flow.

grabTypeAndFlags
The type and flags for the input flow grab affected 
by this alteration. The high byte contains a record 
of VisInputFlowGrabType, described below; the 
low byte contains a VisInputFlowGrabFlags 
record, also described below.

Return:	Nothing.

Interception:	Any VisContent object that uses a large graphics space should subclass 
this method. In the handler, it should apply the stated translation, then 
call its superclass. Each subsequent mouse event will have the 
translation applied before being passed on to the composite's children.

Structures:	The types of VisInputFlowGrabType are listed below:

VIFGT_ACTIVE	The affected grab type is the active grab.

VIFGT_PRE_PASSIVE
The affected grab type is the pre-passive grab.

VIFGT_POST_PASSIVE
The affected grab type is the post-passive grab.

The flags of VisInputFlowGrabFlags are listed below:

VIFGF_NOT_HERE	Flag set to indicate that the message should not be 
handled in this method but rather passed up the 
tree with this flag cleared. It is used to distinguish 
between requests made by other objects and 
requests made by an object sent to itself. It also 
allows an object to redirect the message to another 
node not in the visible hierarchy by handling the 
message and passing it in a direction other than up 
the visible tree. This overrides all the other flags in 
this record.

VIFGF_FORCE	Flag set if the grab should be forced. Note that both 
VIFGF_GRAB and VIFGT_ACTIVE must also be 
specified.

VIFGF_GRAB	Flag set if the grab is being made, clear if the grab 
is being released. In either case, object must be 
passed-if a release, the grab will not be released 
unless the objects match. Note also that only one 
object may have the active grab, but many objects 
may have either passive grab at a given time.

VIFGF_KBD	Flag set if action is a keyboard grab or release.

VIFGF_MOUSE	Flag set if action is a mouse grab or release.

VIFGF_LARGE	Flag set if large mouse events are affected by the 
flow alteration. VIFGF_MOUSE must also be set.

VIFGF_PTR	Flag set if mouse grab and pointer events are 
requested. If flag clear, only button-related events 
will be sent. VIFGF_MOUSE must also be set.

n	MSG_VIS_RELEASE_MOUSE

void	MSG_VIS_RELEASE_MOUSE();

A visible object sends itself this message if it has the mouse grab and wants 
to release it. Typically, this message will be called in the object's 
MSG_META_END_SELECT handler. It works for both large and small grabs.

Source:	Any visible object.

Destination:	Any visible object-typically sent by the object to itself.

Interception:	Unlikely.

Code Display 23-2 Grabbing and Releasing the Mouse

/* This code display shows the MSG_META_START_SELECT, MSG_META_END_SELECT,
 * and MSG_VIS_LOST_GADGET_EXCL handlers from the TicTac sample application.
 *
 * The sequence of input events and the messages they generate follow the
 * following basic patterns:
 * 1.	User presses select button
 *	MSG_META_START_SELECT generated, sent to object under mouse pointer
 *	If object under pointer is a game piece,
 *		Game piece grabs gadget exclusive
 *		Game piece grabs mouse
 * 2.	User holds button and drags mouse
 *	MSG_META_DRAG_SELECT generated, sent to object with mouse grab
 *		Game piece sets internal "dragging" flag
 *		Game piece draws outline
 *	MSG_META_PTR messages generated during drag, sent to object with mouse grab
 *		Game piece erases previous outline
 *		Game piece draws new outline at new pointer position
 * 3.	User releases button
 *	MSG_META_END_SELECT generated, sent to object with mouse grab
 *		Game piece releases gadget exclusive (MSG_VIS_RELEASE_GADGET_EXCL)
 *		MSG_VIS_LOST_GADGET_EXCL generated, sent to mouse grab (game piece)
 *		Game piece erases old outline, if any
 *		Game piece moves itself, erases old bounds, draws new bounds
 *		Game piece releases mouse grab (MSG_VIS_RELEASE_MOUSE)
 */

/***********************************************************************
 *		MSG_META_START_SELECT for TicTacPieceClass
 ***********************************************************************
 * SYNOPSIS:		Grabs the mouse and calls for future pointer events.
 * 		When the user clickes in the view, TicTacView will pass
 * 		the click event to TicTacBoard. Since TicTacBoardClass
 * 		does not intercept the event, VisContentClass passes
 * 		it on to its child object currently under the pointer.
 * PARAMETERS:
 * 	void	(MouseReturnParams *retVal,
 *		 word xPosition, word yPosition, word inputState);
 *
 * STRATEGY:		When the piece object receives this message, it means
 * 		it has been clicked on by the user and the mouse button
 * 		is still down. The piece must grab the mouse so that it
 * 		gets all future mouse events, and it must request that
 * 		all future mouse events be sent to it. This ensures
 * 		that if the pointer leaves the object's bounds while
 * 		the button is still pressed, the piece object will still
 * 		receive all the pointer events (otherwise they would be
 * 		sent to whatever object was under the new pointer position).
 ***********************************************************************/

@method TicTacPieceClass, MSG_META_START_SELECT {

	/* Grab the gadget exclusive so we're allowed to grab the mouse. */
    @call @visParent::MSG_VIS_TAKE_GADGET_EXCL(oself);

	/* Grab the mouse. This requests that all future pointer
	 * events be passed directly to this game piece. */
    @call self::MSG_VIS_GRAB_MOUSE();

	/* Finally, return that this particular click event has been processed.
	 * If this flag is not returned, the system will send out the click
	 * event again. */
    retVal->flags = MRF_PROCESSED;					 /* this event processed */
}

/***********************************************************************
 *		MSG_META_END_SELECT for TicTacPieceClass
 ***********************************************************************
 * SYNOPSIS:		This message is received when the selection button has
 * 		been released and this game piece had the mouse grab.
 * 		All it does is release the gadget exclusive.
 * PARAMETERS:
 * 	void	(MouseReturnParams *retVal,
 * 		 word xPosition, word yPosition, word inputState);
 ***********************************************************************/

@method TicTacPieceClass, MSG_META_END_SELECT {
    @call @visParent::MSG_VIS_RELEASE_GADGET_EXCL(oself);
    retVal->flags = MRF_PROCESSED;					/* this event processed */
}

/***********************************************************************
 *		MSG_VIS_LOST_GADGET_EXCL for TicTacPieceClass
 ***********************************************************************
 * SYNOPSIS:		This message is received when the selection button has
 * 		been released and this game piece had the mouse grab.
 * 		It first checks to see if the new, proposed bounds are
 * 		on the game board. If the bounds are valid, then
 * 		it sets the objects VI_bounds field to the new values
 * 		and causes the object to erase its original drawing
 * 		and draw itself at its new bounds. If the bounds are
 * 		not on the game board, it will retain the original bounds
 * 		and redraw using them.
 * PARAMETERS:		void ();
 ***********************************************************************/

@method TicTacPieceClass, MSG_VIS_LOST_GADGET_EXCL {
    WindowHandle win;				/* window handle of view window */
    GStateHandle gstate;				/* temporary gstate to draw to */

    /* See if piece was being dragged or not. If so, clear the outline. */

    if (pself->TTP_dragging) {

	    /* Get the window handle of the view window and create a
	     * temporary gstate for it to draw to. */

	win = @call TicTacView::MSG_GEN_VIEW_GET_WINDOW();
	gstate = GrCreateState(win);

	    /* Set the line color and mode for drawing the outline. */

	GrSetLineColor(gstate, CF_INDEX, C_BLACK, 0, 0);
	GrSetMixMode(gstate, MM_INVERT);

	    /* Erase outline on screen. */

	    /* If the game piece type is TTPT_BOX, draw a rectangle
	     * outline. Otherwise draw an ellipse outline. */

	if (pself->TTP_pieceType == TTPT_BOX) {
	    GrDrawRect(gstate, pself->TTP_horizPos, pself->TTP_vertPos,
			 ((pself->TTP_horizPos) + PIECE_WIDTH),
			 ((pself->TTP_vertPos) + PIECE_HEIGHT));
	} else {
	    GrDrawEllipse(gstate, pself->TTP_horizPos, pself->TTP_vertPos,
			 ((pself->TTP_horizPos) + PIECE_WIDTH),
			 ((pself->TTP_vertPos) + PIECE_HEIGHT));
	}

	    /* Check to see if the new bounds are on the game board. If
	     * they are, set the object's bounds to the new values. If
	     * the are not, retain the original values and set the values
	     * to those last stored. */

	if (@call TicTacBoard::MSG_TICTAC_VALIDATE_BOUNDS(
			((pself->TTP_vertPos) + PIECE_HEIGHT),
			((pself->TTP_horizPos) + PIECE_WIDTH),
			pself->TTP_vertPos, pself->TTP_horizPos)) {

	    /* Invalidate the original drawing of the game piece. Send
	     * the VI_bounds rectangle as the parameters because they have
	     * not been changed since the START_SELECT. This message is
	     * the equivalent of calling GrInvalRect() with the same bounds */

	    @call self::MSG_VIS_BOUNDS_CHANGED(pself->VI_bounds.R_bottom,
					pself->VI_bounds.R_right,
					pself->VI_bounds.R_top,
					pself->VI_bounds.R_left);

	    /* Set the game piece object's bounds to the new coordinates. */

	    pself->VI_bounds.R_left = pself->TTP_horizPos;
	    pself->VI_bounds.R_right = (pself->TTP_horizPos) + PIECE_WIDTH;
	    pself->VI_bounds.R_top = pself->TTP_vertPos;
	    pself->VI_bounds.R_bottom = (pself->TTP_vertPos) + PIECE_HEIGHT;

	} else {

	    /* If the bounds are not on the game board, then reset the
	     * current positions to be the original bounds. */

	    pself->TTP_horizPos = pself->VI_bounds.R_left;
	    pself->TTP_vertPos = pself->VI_bounds.R_top;
	}

	    /* Now, the game piece must draw itself at its newly-set
	     * bounds (will draw itself over its original picture if the
	     * new bounds were invalid). */

	@call self::MSG_VIS_DRAW(0, gstate);

	    /* Finally, destroy the temporary gstate used for drawing. */

	GrDestroyState(gstate);

	    /* Clear flag to indicate we are no longer dragging. */

	pself->TTP_dragging = FALSE;
    }
	/* Release the mouse grab now that the move has finished.
	 * Other objects in the view (other game pieces, for example)
	 * may now receive pointer, select, and drag events. */

    @call self::MSG_VIS_RELEASE_MOUSE();
}



		Passive Grabs

MSG_VIS_ADD_BUTTON_PRE_PASSIVE, 
MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE, 
MSG_VIS_ADD_BUTTON_POST_PASSIVE, 
MSG_VIS_REMOVE_BUTTON_POST_PASSIVE

They type of mouse grab described in the previous section is also known as 
an "active" mouse grab. An object can also have two other types of mouse 
grabs: pre-passive and post-passive. While only one object may have the 
active mouse grab at any given time, any number of objects may have pre- or 
post-passive grabs on the mouse.

An object with a pre-passive mouse grab receives a copy of the input event 
before the event goes to its true destination. The copy will be a message of the 
form MSG_META_PRE_PASSIVE_- (e.g., if the event is MSG_META_PTR, the 
pre-passive event is MSG_META_PRE_PASSIVE_PTR). All pre-passive events 
will be handled before the true event is delivered to the object with the active 
grab. If any of the pre-passive copies of the event is returned with the flag 
MRF_PREVENT_PASS_THROUGH, the active event will not be sent to its 
destination. You can use this feature to set up input filters, having an object 
receive all mouse events pre-passive and filtering out those that should not 
be delivered. The message MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE 
removes any pre-passive mouse grab from the object.

A post-passive mouse grab is similar to a pre-passive except that the 
post-passive object receives the event after it is sent to its normal destination. 
The post-passive object will receive a MSG_META_POST_PASSIVE_- with the 
same flags and position information as sent with the input event. An object 
that has the post-passive grab can release it by sending itself a 
MSG_VIS_REMOVE_BUTTON_POST_PASSIVE.

n	MSG_VIS_ADD_BUTTON_PRE_PASSIVE

void	MSG_VIS_ADD_BUTTON_PRE_PASSIVE();

A visible object sends itself this message (with @call) when it wants to gain 
a pre-passive mouse grab. The object will receive all subsequent mouse 
events in the form of MSG_META_PRE_PASSIVE_- before the event's 
destination object receives them; this message will carry the same input 
information as passed with the input event. The object should handle 
MSG_META_PRE_PASSIVE_- and, if the event is not to be sent normally to 
its destination, should return the flag MRF_PREVENT_PASS_THROUGH from 
that handler. The pre-passive grab will be released when the object sends 
itself a MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself when it 
wants to gain a pre-passive mouse grab.

Interception:	Unlikely-Note that the object must, however, intercept any 
MSG_META_PRE_PASSIVE- events it is interested in.

n	MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE

void	MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE();

This message removes the pre-passive grab from a visible object.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself when it has 
a pre-passive grab and wants to release it.

Interception:	Unlikely.

n	MSG_VIS_ADD_BUTTON_POST_PASSIVE

void	MSG_VIS_ADD_BUTTON_POST_PASSIVE();

A visible object sends itself this message (with @call) when it wants to gain 
the post-passive mouse grab. The object will receive all subsequent mouse 
events in the form of MSG_META_POST_PASSIVE_- after the event's 
destination object receives them; this message will carry the same input 
information as passed with the input event. The object should handle the 
appropriate MSG_META_POST_PASSIVE_- to properly receive the events. 
The post-passive grab will be released when the object receives a 
MSG_VIS_REMOVE_BUTTON_POST_PASSIVE.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself when it 
wants to receive post-passive input events.

Interception:	Unlikely-Note that the object must, however, handle any 
MSG_META_POST_PASSIVE_- events it is interested in.

n	MSG_VIS_REMOVE_BUTTON_POST_PASSIVE

void	MSG_VIS_REMOVE_BUTTON_POST_PASSIVE();

This message removes any post-passive mouse grab from the object.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself to release 
a post-passive mouse grab.

Interception:	Unlikely.

		The Gadget Exclusive and Focus Hierarchy

MSG_VIS_TAKE_GADGET_EXCL, MSG_VIS_RELEASE_GADGET_EXCL, 
MSG_VIS_LOST_GADGET_EXCL, MSG_VIS_VUP_QUERY_FOCUS_EXCL, 
MSG_VIS_FUP_QUERY_FOCUS_EXCL, 
MSG_VIS_VUP_ALLOW_GLOBAL_TRANSFER

The gadget exclusive is a marker in the system used by the UI to indicate 
which object has exclusive access to input gadget functionality. Only one 
gadget at a time may have the gadget exclusive, and the gadget exclusive 
may be forcibly taken from an object by another object (for example, when a 
system-modal dialog comes up during a drag operation).

At times, an object will force the mouse input to go to a different object from 
that which has the current active grab. This is done almost exclusively by the 
Specific UI library and is rarely, if ever, done by applications. Three messages 
can be used in determining which object has the current "gadget exclusive," 
or active mouse grab. These are shown below.

In addition, individual objects can get information about the current state of 
the Focus hierarchy with MSG_VIS_VUP_QUERY_FOCUS_EXCL and 
MSG_VIS_FUP_QUERY_FOCUS_EXCL, also shown below.

To deal with a quick-transfer operation, a visible object may also have to use 
the message MSG_VIS_VUP_ALLOW_GLOBAL_TRANSFER. This message may 
be used to remove the mouse grab from the GenView in which the visible 
object resides, thereby allowing mouse events to reach other objects outside 
the view window.

n	MSG_VIS_TAKE_GADGET_EXCL

void	MSG_VIS_TAKE_GADGET_EXCL(

	optr	child);

This message causes the passed object to be given the gadget exclusive. Any 
object currently having the gadget exclusive will subsequently receive a 
MSG_VIS_LOST_GADGET_EXCL. This is used primarily by the Specific UI.

Source:	Unrestricted. Typically sent by a visible object that will next grab the 
mouse.

Destination:	Any visible object-normally sent by an object to its visible parent.

Parameters:	child	The optr of the object to which the gadget exclusive 
will be given (normally the calling object).

Return:	Nothing.

Interception:	Unlikely.

See Also:	MSG_VIS_GRAB_MOUSE, MSG_VIS_LOST_GADGET_EXCL

n	MSG_VIS_RELEASE_GADGET_EXCL

void	MSG_VIS_RELEASE_GADGET_EXCL(

	optr	child);

This message causes the passed object to release the gadget exclusive. The 
object specified by child will then receive a MSG_VIS_LOST_GADGET_EXCL.

Source:	Unrestricted. Typically sent by an object that has a mouse grab and 
expects to release it.

Destination:	Any visible object-normally sent by the object to it's parent.

Parameters:	child	The optr of the object which is to lose the gadget 
exclusive (normally the calling object).

Return:	Nothing.

Interception:	Unlikely.

See Also:	MSG_VIS_RELEASE_MOUSE, MSG_VIS_LOST_GADGET_EXCL

n	MSG_VIS_LOST_GADGET_EXCL

void	MSG_VIS_LOST_GADGET_EXCL();

This message, when received, indicates that the recipient has lost its hold on 
the gadget exclusive. When an object receives this, it should release the 
active mouse grab, if appropriate.

Source:	Unrestricted-typically sent by the UI.

Destination:	The visible object losing the gadget exclusive.

Interception:	Mouse grabs should be released in this handler.

n	MSG_VIS_VUP_QUERY_FOCUS_EXCL

void	MSG_VIS_VUP_QUERY_FOCUS_EXCL(

	ObjectAndGrabParams *retValue);

This message queries up the visible hierarchy to find the object having the 
current focus in the current window. The current window is taken to be the 
window in which the object receiving the message resides.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself to find the 
focus optr in its window.

Parameters:	retValue	A pointer to an empty ObjectAndGrabParams 
structure, shown below.

Return:	The ObjectAndGrabParams structure pointed to by retVal will be 
filled with the appropriate data.

Interception:	Unlikely.

Structures:	The structure of the ObjectAndGrabParams is shown below:

typedef struct {
    word		OAGP_grabFlags;  /* flags */
    word		OAGP_unused;     /* reserved */
    optr		OAGP_object;     /* object with focus */
} ObjectAndGrabParams;

The OAGP_grabFlags field contains a record of HierarchicalGrabFlags, 
defined in "Input," Chapter 11 of the Concepts Book. The allowable flags are

HGF_SYS_EXCL	Indicates this object has the system exclusive.

HGF_APP_EXCL	Indicates this object has the application's exclusive.

HGF_GRAB	Indicates this object wishes to grab the exclusive (if 
clear, the object wishes to release), when passed as 
a parameter. In the structure, it merely indicates 
that the object in OAGP_object has the exclusive.

HGF_OTHER_INFO
Twelve bits used by the specific UI depending on 
the type of hierarchical grab.

n	MSG_VIS_FUP_QUERY_FOCUS_EXCL

void	MSG_VIS_FUP_QUERY_FOCUS_EXCL(

	ObjectAndGrabParms *retValue);

This message queries the focus hierarchy to see which object has the current 
focus. The current focus object does not have to be in the caller's visible tree.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	retValue	A pointer to an empty ObjectAndGrabParams 
structure, shown above in the entry for 
MSG_VIS_VUP_QUERY_FOCUS_EXCL.

Return:	The ObjectAndGrabParams structure pointed to by retVal will be 
filled with the appropriate data.

Interception:	Unlikely.

Structures:	The structure of the ObjectAndGrabParams is shown in the entry 
for MSG_VIS_VUP_QUERY_FOCUS_EXCL.

n	MSG_VIS_VUP_ALLOW_GLOBAL_TRANSFER

void	MSG_VIS_VUP_ALLOW_GLOBAL_TRANSFER();

This message is sent by a visible object to itself when a quick-transfer 
operation is underway and the pointer has to be allowed to leave the bounds 
of the object's view window. This message will travel up to the content object, 
which will indicate to the GenView that the pointer events must be allowed 
to go to other windows in the system.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself when the 
global transfer must be allowed outside its window.

Interception:	Unlikely.

		The Mouse Status

MSG_VIS_VUP_SET_MOUSE_INTERACTION_BOUNDS, 
MSG_VIS_VUP_GET_MOUSE_STATUS, 
MSG_VIS_VUP_TERMINATE_ACTIVE_MOUSE_FUNCTION, 
MSG_VIS_VUP_BUMP_MOUSE

The UI can control the mouse image and events as they occur. Because the UI 
is based on the visible classes, the messages that control the mouse status are 
also available to you, though they will probably be of very little utility. These 
messages are given below.

n	MSG_VIS_VUP_SET_MOUSE_INTERACTION_BOUNDS

void	MSG_VIS_VUP_SET_MOUSE_INTERACTION_BOUNDS(@stack

	int	bottom,

	int	right,

	int	top,

	int	left);

A visible object requesting the mouse grab sends this message up the visible 
tree. This message will be handled by a content object. It indicates a new set 
of draggable bounds in case the user initiates a drag-scrolling operation. This 
message is sent automatically when the visible object requests the grab.

Source:	A visible object requesting a mouse grab.

Destination:	The sender sends this message to itself.

Parameters:	bottom, right, top, left
The four bounds of the new bounding rectangle. 
Default is the bounds of the object sending the 
message.

Return:	Nothing.

Interception:	Unlikely.

n	MSG_VIS_VUP_GET_MOUSE_STATUS

word	MSG_VIS_VUP_GET_MOUSE_STATUS();

This message is rarely used by any objects outside the UI library. It returns 
the information passed with the last mouse event. The word return value 
contains two byte-sized sets of flags. The high byte is a list of the active UI 
functions, and the low byte represents the current button information.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself when it can 
not locally store the latest mouse information.

Parameters:	None.

Return:	A word containing two values: The high word is a record of type 
UIFunctionsActive, and the low word is a word of ButtonInfo.

Interception:	Unlikely.

n	MSG_VIS_VUP_TERMINATE_ACTIVE_MOUSE_FUNCTION

void	MSG_VIS_VUP_TERMINATE_ACTIVE_MOUSE_FUNCTION();

This message is sent by a visible object to itself to terminate any active mouse 
function, forcing it to be a function of type "other." This message is used only 
by the Specific UI library in cases where input synchronization problems 
occur in specific places. Applications should generally not use this message.

Source:	A visible object handling active input events.

Destination:	Sent by the visible object to itself.

Interception:	This message should not be subclassed.

n	MSG_VIS_VUP_BUMP_MOUSE

void	MSG_VIS_VUP_BUMP_MOUSE(

	int	xBump,

	int	yBump);

This message causes the UI to bump the pointer image on the screen by the 
passed offsets as if the user had moved the mouse. It's unlikely your objects 
will subclass this message; you may, however, use it to bump the mouse. It is 
most often used by specific UI objects (menus, scrollers) that make the mouse 
follow their movements.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	xBump	The horizontal amount to bump the mouse.

yBump	The vertical amount to bump the mouse.

Return:	Nothing.

Interception:	Unlikely.

	23.4.4.2	Keyboard Events

MSG_META_GRAB_KBD, MSG_META_FORCE_GRAB_KBD, 
MSG_META_RELEASE_KBD

The keyboard, like the mouse, may be grabbed by visible objects. Keyboard 
events arrive in the form MSG_META_KBD_CHAR; a single message 
represents all different types of keyboard events (unlike mouse events, which 
can be much more diverse).

To grab the keyboard, the visible object should send itself the message 
MSG_META_GRAB_KBD. If the grab should be made in any circumstances, 
the object should use MSG_META_FORCE_GRAB_KBD. To release the 
keyboard grab, the object should send itself MSG_META_RELEASE_KBD.

n	MSG_META_GRAB_KBD

void	MSG_META_GRAB_KBD();

A visible object will send itself this message (using @call) when it wants to 
gain the keyboard grab. To release the grab, it must send itself a 
MSG_META_RELEASE_KBD. If it wants to gain the exclusive regardless of 
whether another object has it, it should use MSG_META_FORCE_GRAB_KBD.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself to gain the 
keyboard grab.

Interception:	Unlikely-Note that the object must, however, intercept 
MSG_META_KBD_CHAR to receive the subsequent keyboard events.

n	MSG_META_FORCE_GRAB_KBD

void	MSG_META_FORCE_GRAB_KBD();

A visible object will send itself this message (using @call) when it wants to 
gain the keyboard grab whether or not another object currently has it. To 
release the grab, the object must later send itself 
MSG_META_RELEASE_KBD.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself to force a 
keyboard grab.

Interception:	Unlikely.

n	MSG_META_RELEASE_KBD

void	MSG_META_RELEASE_KBD();

A visible object that has the keyboard grab must send itself this message to 
release the grab.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself to release 
its keyboard grab.

Interception:	Unlikely.

	23.4.4.3	Ink and Pen Events

MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK

If a visible object expects and wants Ink input, it should subclass the message 
MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK. This message queries the 
visible object, which should return specific values based on the current input 
state and object bounds.

This message has two default handlers; the default VisClass handler always 
returns false, indicating that the visible object does not expect Ink input. You 
can, however, substitute a second default handler for the VisClass handler 
by adding the following line to your Goc file after the object's class definition:

@method VisObjectHandlesInkReply, <YourClass>,
                MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK;

This will, in essence, substitute the system-provided routine 
VisObjectHandlesInkReply() for a subclassed message handler. This 
routine will do the right thing for the object in interacting with the input 
manager. All subsequent input events will be considered Ink events.

n	MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK

void	MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK(

	VisCallChildrenInBoundsFrame					*data);

This message is subclassed by objects that handle Ink input. See above for 
directions on handling this message. The parameters are five data words that 
may be modified and the bounds of a rectangle. This message will be sent to 
all objects whose bounds fall within the passed rectangle.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	data	A pointer to a VisCallChildrenInBoundsFrame 
structure containing the bounding rectangle and 
five words of data. This structure is described 
below.

Return:	Three fields of the VisCallChildrenInBoundsFrame structure 
pointed to by data will have meaning on return. See the Interception 
paragraph below to determine whether the return values should be set 
or not in a subclassed handler.

VCCIBF_data1	Memory handle of the top object desiring ink.

VCCIBF_data2	Chunk handle of the top object desiring ink.

VCCIBF_data3	Upper bound of the object desiring ink.

Interception:	If an object wants to receive ink messages, it should do the following 
things in its handler for this message: First compare the passed 
VCCIBF_data3 value with the top bound of the object. Then, if the 
upper bound of the object is less than the VCCIBF_data3 value (or if the 
value in VCCIBF_data1 is zero), then the object should return the 
values indicated in the Return paragraph above. Otherwise, if these 
conditions are not met, it should return with the structures and 
registers unchanged.

Structures:	The VisCallChildrenInBoundsFrame structure is shown below:

typedef struct {
	word		VCCIBF_data1;
	word		VCCIBF_data2;
	word		VCCIBF_data3;
	word		VCCIBF_data4;
	word		VCCIBF_data5;
		/* Five data words as described above */
	Rectangle		VCCIBF_bounds;
		/* bounds must be in the coordinate
		 * system of the parent of the caller */
} VisCallChildrenInBoundsFrame;

	23.5	Working with Visible Object 
Trees

Visible objects can not be used unless they are placed within object trees. The 
top object of the tree must be of a subclass of VisContentClass. Other 
objects in the tree can be of any visible object class. Keep in mind, however, 
that VisClass objects can not have children; only the composite classes 
(VisCompClass and VisContentClass) may have children. Therefore, 
VisClass is useful only for leaf objects.

Each visible object has a VI_link instance field. This field specifies the optr of 
that object's next sibling in the tree. Since this is a field of VisClass, both 
composites and noncomposites have it. Composite objects also have a 
VCI_comp field which contains the optr of the composite's first child. Thus, 
visible trees use the same format as normal object trees.

	23.5.1	Creating and Destroying

MSG_VIS_DESTROY

Visible objects are just like any other objects in the ways they are created and 
destroyed. You can create visible objects in many ways; the easiest is to set 
them up in a resource and simply load or duplicate the resource block at 
run-time. You can also use the ObjInstantiate() routine to instantiate new 
visible objects on the fly from your predefined subclass of VisClass, 
VisCompClass, or VisContentClass. "GEOS Programming," Chapter 5 of 
the Concepts Book, details how to instantiate a new object of a given class.

Destroying visible objects is very simple. You only need to use the message 
MSG_VIS_DESTROY, which works on a visible object and all its children (if it 
has any). This message removes the visible branch from the screen if 
necessary, detaches the visible objects from the visible tree, and then 
destroys the object (freeing its instance chunk). The only thing the object 
must do is clean up after itself-in its MSG_META_DETACH or 
MSG_META_FINAL_OBJ_FREE handler, it should free any memory that it 
allocated explicitly for its own use, for example.

MSG_VIS_DESTROY also marks the destroyed object's parent invalid both in 
geometry and image so the tree will be updated properly.

n	MSG_VIS_DESTROY

void	MSG_VIS_DESTROY(

	VisUpdateMode updateMode);

This message is the high level routine for destroying branches of visible trees. 
This message will close and destroy the entire branch, unlinking any visible 
objects in the branch under the recipient object. The parent of the removed 
branch will be marked invalid for later visual update. This message may be 
subclassed to replace the geometry update handling, but this is not easily 
done and is rare.

Source:	Unrestricted.

Destination:	Any visible object (or head of a visible branch).

Parameters:	updateMode	A VisUpdateMode that determines when the 
visible parent of the destroyed object/branch will be 
updated on the screen.

Return:	Nothing.

Interception:	Unlikely-may be subclassed if the parent is not to be marked invalid. 
This is extremely rare.

	23.5.2	Adding and Removing

MSG_VIS_ADD_CHILD, MSG_VIS_REMOVE, MSG_VIS_REMOVE_CHILD, 
MSG_VIS_MOVE_CHILD, MSG_VIS_ADD_NON_DISCARDABLE_VM_CHILD, 
MSG_VIS_REMOVE_NON_DISCARDABLE_VM_CHILD, 
MSG_VIS_REMOVE_NON_DISCARDABLE

Once you have objects instantiated, you can connect them together into an 
object tree. If you know the structure of your tree beforehand, you can create 
the tree explicitly in your .goc file, just as you would create your generic 
object tree.

For many purposes, however, a dynamic object tree is much more useful. To 
use it, you must be able to add and remove objects easily as well as move 
them within the tree easily.

	23.5.2.1	Adding and Removing Normally

To add an object to a branch of a visible tree, use the message 
MSG_VIS_ADD_CHILD. This message adds a visible object as the child of a 
composite; if the new child is a composite with its own children, the entire 
branch is added to the tree. You can add a child at any position in the 
composite's child list (e.g., as the first child, as the second child, as the last 
child, etc.), and you can mark the child dirty after addition if you want.

For example, if you have a composite visible object with two children that is 
currently unattached to any visible tree, you can attach it to a tree with 
MSG_VIS_ADD_CHILD. Figure 23-4 shows this process and the line of code 
used to add the composite as the second child of an object in the tree.

Note that the child in the example is added as child one. The child list of a 
composite is zero-based, so the first child is referred to as number zero, the 
second is number one, and so on. The last child may always be referred to as 
CCO_LAST; likewise, the first child may always be referred to as CCO_FIRST.

To remove an object or branch from a visible tree, you can use either 
MSG_VIS_REMOVE or MSG_VIS_REMOVE_CHILD. MSG_VIS_DESTROY may 
also be used, but only if the entire branch should be destroyed after being 
removed from the tree. Both MSG_VIS_REMOVE and 
MSG_VIS_REMOVE_CHILD detach the object from the visible tree and 
visually update the parent immediately. MSG_VIS_REMOVE, however, should 
be sent directly to the object being removed, while MSG_VIS_REMOVE_CHILD 
is sent to the parent of the object being removed. When removing a child from 
its parent, you can specify the child by position number (e.g., remove the last 
child or the first child).

You can move a child within its child list with MSG_VIS_MOVE_CHILD. This 
message is sent to the parent and simply moves the child within the parent's 
child list. To move a child from one parent to another, you must first remove 
it and then add it to the other parent with MSG_VIS_REMOVE_CHILD and 
MSG_VIS_ADD_CHILD. This message, as the others, will move the child's 
entire branch with it.

	23.5.2.2	Adding and Removing Objects Not Saved to 
Documents

In many cases, you may save visible objects directly to VM documents using 
GenDocument objects and the document controllers. In cases like this, the 
objects you save to the file must not be discarded by the UI if the visible object 
is taken off the tree or removed. These objects are known as 
"non-discardable" visible objects stored in a VM file, and unless they're 
handled specially, they can cause your documents to crash your application.

Any top-level object you save directly to a file must be treated as 
non-discardable. That is, any object that gets dynamically added to or 
removed from a visible tree (such as a vis object that gets added as the child 
of a GenDocument when the document is opened) must be added, removed, 
and managed as a non-discardable object. There are three messages that deal 
specifically with non-discardable visible objects; these are detailed below and 
are MSG_VIS_ADD_NON_DISCARDABLE_VM_CHILD, 
MSG_VIS_REMOVE_NON_DISCARDABLE_VM_CHILD, and 
MSG_VIS_REMOVE_NON_DISCARDABLE.

n	MSG_VIS_ADD_CHILD

void	MSG_VIS_ADD_CHILD(

	optr		child,

	CompChildFlags		flags);

This message attaches the passed object as a child of the composite handling 
the message. If the parent is already opened and on the screen, you must 
invalidate the child with MSG_VIS_MARK_INVALID, passing the invalidation 
VOF_WINDOW_INVALID; the composite and child will be updated 
appropriately according to the VisUpdateMode passed with the 
invalidation. If, however, the parent is not opened, the child will 
automatically be opened when the parent is opened.

Source:	Unrestricted.

Destination:	Any visible composite object.

Parameters:	child	The optr of the visible object to be added as a child.

flags	A structure of CompChildFlags, described below.

Return:	Nothing.

Interception:	You should not subclass this message.

Structures:	The CompChildFlags structure contains one one-bit flag and one 
15-bit unsigned numerical field. These are described below and can be 
found in metaC.goh.

typedef WordFlags CompChildFlags;
#define CCF_MARK_DIRTY					0x8000
#define CCF_REFERENCE					0x7fff

#define CCO_FIRST					0x0000
#define CCO_LAST					0x7FFF

#define CCF_REFERENCE_OFFSET					     0

CCF_MARK_DIRTY	If this flag is set, the object will be marked dirty 
when added to the tree.

CCF_REFERENCE	The zero-based position of the new child. Other 
children will be shuffled forward in the child list as 
necessary. If greater than the number of children, 
it will be taken to be CCO_LAST.

Two special numbers may be used in the CCF_REFERENCE field:

CCO_FIRST	Add as the first child.

CCO_LAST	Add as the last child.

Warnings:	Do not pass the optr of an object that is already the child of another 
object. The results are unpredictable and will likely result in an error.

n	MSG_VIS_REMOVE

void	MSG_VIS_REMOVE(

	VisUpdateMode updateMode);

This is the high-level message that closes (if necessary) and removes a visible 
branch from the object tree. The parent of the branch is marked invalid for 
visual update according to the passed VisUpdateMode.

Unlike MSG_VIS_DESTROY, this message does not destroy the visible branch 
but only unlinks it from the tree. This message may not be subclassed by any 
object. This message is useful for hiding visible branches which may be added 
again later with MSG_VIS_ADD_CHILD.

Source:	Unrestricted.

Destination:	Any visible composite object.

Parameters:	updateMode	The VisUpdateMode used to update the 
composite from which the child is removed. 
VUM_MANUAL is not allowed.

Return:	Nothing.

Interception:	Do not subclass this message.

Warnings:	This message will not allow VUM_MANUAL to be passed as the 
updateMode.

n	MSG_VIS_REMOVE_CHILD

void	MSG_VIS_REMOVE_CHILD(

	optr		child,

	CompChildFlags		flags);

This message removes the specified child from the object tree. This message 
should be rarely used and used with care; it does not close the visible branch 
but simply removes it. Consider using the higher-level MSG_VIS_REMOVE 
instead. Note that all grabs (focus, gadget, mouse, etc.) must be released by 
the child and all its children before the branch can be removed safely.

Source:	Unrestricted.

Destination:	The parent composite of the passed object.

Parameters:	child	The optr of the child to be removed. If this optr is 
not among the recipient's children, an error will 
likely occur.

flags	The CompChildFlags as described in 
MSG_VIS_ADD_CHILD on page 1377.

Return:	Nothing.

Interception:	You should not subclass this message.

Warnings:	Most likely you should use MSG_VIS_REMOVE instead of this message. 
MSG_VIS_REMOVE takes care of extra bookkeeping automatically that 
can be difficult.

n	MSG_VIS_MOVE_CHILD

void	MSG_VIS_MOVE_CHILD(

	optr		child,

	CompChildFlags		flags);

This message moves a child of the recipient to another location among its 
siblings. It essentially removes the child from the branch and then re-adds it 
in the same manner as MSG_VIS_ADD_CHILD. This message does not move 
the child from one parent to another; you must use a combination of 
MSG_VIS_REMOVE and MSG_VIS_ADD_CHILD to achieve that.

Source:	Unrestricted.

Destination:	The parent composite of the passed object.

Parameters:	child	The optr of the child to be removed. If this optr is 
not among the recipient's children, an error will 
likely occur.

flags	The CompChildFlags as described in 
MSG_VIS_ADD_CHILD on page 1377.

Return:	Nothing.

Interception:	You should not subclass this message.

n	MSG_VIS_ADD_NON_DISCARDABLE_VM_CHILD

void	MSG_VIS_ADD_NON_DISCARDABLE_VM_CHILD(

	optr		child,

	CompChildFlags		flags);

This message performs exactly the same as MSG_VIS_ADD_CHILD except 
that it also increments the object's in-use count so it will never be discarded. 
This is used on top objects in visible sub-trees that are saved to document 
files: The object is added as a non-discardable file when the document is 
opened, and it is removed as a non-discardable child (with 
MSG_VIS_REMOVE_NON_DISCARDABLE_VM_CHILD or 
MSG_VIS_REMOVE_NON_DISCARDABLE) when the document is closed.

Source:	Unrestricted-typically a document object when opening the file.

Destination:	The new parent of the visible object being added to the tree.

Parameters:	child	The optr of the new child being added to the tree.

flags	A record of CompChildFlags indicating where the 
child should be added. CCF_MARK_DIRTY is 
ignored in this record.

Return:	Nothing.

Interception:	Generally not intercepted.

n	MSG_VIS_REMOVE_NON_DISCARDABLE_VM_CHILD

void	MSG_VIS_REMOVE_NON_DISCARDABLE_VM_CHILD(

	optr	child);

This message performs exactly the same as MSG_VIS_REMOVE_CHILD 
except that it is used with MSG_VIS_ADD_NON_DISCARDABLE_VM_CHILD 
rather than with MSG_VIS_ADD_CHILD. This message decrements the in-use 
count before removing the child, thereby undoing the extra increment 
performed by MSG_VIS_ADD_NON_DISCARDABLE_VM_CHILD.

Source:	Unrestricted-typically a document object when closing the file.

Destination:	The parent of the visible object being removed from the tree.

Parameters:	child	The optr of the child being removed.

Return:	Nothing.

Interception:	Generally not intercepted.

n	MSG_VIS_REMOVE_NON_DISCARDABLE

void	MSG_VIS_REMOVE_NON_DISCARDABLE(

	VisUpdateMode		updateMode)

This message performs exactly the same as MSG_VIS_REMOVE except that it 
decrements the object's in-use count before removing it. This message should 
therefore be used in conjunction with the adding message 
MSG_VIS_ADD_NON_DISCARDABLE_VM_CHILD and should not be used with 
MSG_VIS_ADD_CHILD. Likewise, MSG_VIS_REMOVE should not be used with 
this MSG_VIS_ADD_NON_DISCARDABLE_VM_CHILD.

Source:	Unrestricted-typically a document object when closing the file.

Destination:	The visible object being removed from the tree.

Parameters:	updateMode	A VisUpdateMode value indicating when the 
object should be visibly removed from the tree. 
VUM_MANUAL is not allowed.

Return:	Nothing.

Interception:	Generally not intercepted.

	23.5.3	Getting Visible Tree Information

MSG_VIS_FIND_CHILD, MSG_VIS_FIND_CHILD_AT_POSITION, 
MSG_VIS_COUNT_CHILDREN, MSG_VIS_FIND_PARENT

When an application manages a visible object tree, it will most likely need to 
find children, count children, or get the optr of a particular object in the tree. 
VisClass offers four messages to provide this bookkeeping information. 
These four messages are listed below.

n	MSG_VIS_FIND_CHILD

word	MSG_VIS_FIND_CHILD(

	optr	object);

This message returns the zero-based position of the specified child among the 
parent's children.

Source:	Unrestricted.

Destination:	Any visible composite object.

Parameters:	object	The optr of the child to be found.

Return:	The zero-based position of the child in the parent's child list. (E.g., the 
first child returns zero, the second child returns one, the third child 
returns two, etc.) If object is not the optr of one of the composite's 
children, the value -1 will be returned. If sent to a non-composite object, 
the message will also return -1.

Interception:	Unlikely.

n	MSG_VIS_FIND_CHILD_AT_POSITION

optr	MSG_VIS_FIND_CHILD_AT_POSITION(

	word	position);

This message returns the optr of the child occupying the position specified 
among the recipient's children.

Source:	Unrestricted.

Destination:	Any visible composite object.

Parameters:	position	The zero-based position of the child whose optr is to 
be returned.

Return:	The optr of the child occupying the passed position. If no child occupies 
that position, or if the message is sent to a non-composite object, the 
retuned value will be NullOptr.

Interception:	Unlikely.

n	MSG_VIS_COUNT_CHILDREN

word	MSG_VIS_COUNT_CHILDREN();

This message returns the number of children the recipient object has. The 
count is not zero-based; if a composite has five children, this message will 
return five.

Source:	Unrestricted.

Destination:	Any visible composite object.

Parameters:	None.

Return:	The number of children the object has. If the object has no children 
(includes non-composite objects), the return will be zero.

Interception:	Unlikely.

n	MSG_VIS_FIND_PARENT

optr	MSG_VIS_FIND_PARENT();

This message returns the optr of the recipient's parent composite.

Source:	Unrestricted.

Destination:	Any visible composite object.

Parameters:	None.

Return:	The optr of the object's parent composite. If the message is sent to the 
top node of a visible tree, the return value will be NullOptr.

Interception:	Unlikely.

Tips:	If you want to send a message to your parent, use the @visParent 
macro defined in the next section.

	23.5.4	Sending Messages Through the Tree

Often an object will need to contact its parent or children but will not know 
their precise optrs. Other times, you may need to send a message to a 
particular object in the tree but don't know where in the tree the object is. 
GEOS provides several ways to dispatch messages to parents and children 
and even to objects of a given class.

	23.5.4.1	Contacting Parents and Children Directly

@visParent, @visChildren, MSG_VIS_CALL_PARENT, 
MSG_VIS_SEND_TO_PARENT, MSG_VIS_SEND_TO_CHILDREN

To send a given message to an object's parent (to check valid bounds, to check 
the parent's state, etc.), you can use the macro @visParent. To do this, 
substitute the macro in place of the destination object's name, as follows:

kids = @call @visParent::MSG_VIS_COUNT_CHILDREN();

The above call is more efficient than using two message calls for the same 
thing, as follows:

myParent = @call self::MSG_VIS_FIND_PARENT();
kids = @call myParent::MSG_VIS_COUNT_CHILDREN();

Note that either @call or @send may be used with the @visParent macro.

A similar macro, @visChildren, is offered for sending messages to a 
composite's children. Note, however, that you can only use the @send 
keyword to send messages with this macro; there is no way for a single call 
to collect return values from many different objects. So, if you need to pass 
pointers to your children, you will have to get each child's optr in turn and 
dispatch the message to it individually. (Recall that pointers should not be 
passed with @send because they may be invalidated by the time the message 
is handled.) The format for using the @visChildren macro is as follows:

@send @visChildren::MSG_VIS_INVALIDATE();

This usage is much more efficient than counting the composite's children and 
using a loop to get the child's optr and send the child the message.

In addition to providing the above macros, VisClass lets you pass recorded 
events to a visible object's parent or children. This can be useful, for example, 
if you need to send a message to another object's parent; you might otherwise 
first have to find the optr of the object's parent and then send the message 
directly. Instead, you can use the VisClass messages 
MSG_VIS_CALL_PARENT and MSG_VIS_SEND_TO_PARENT to pass recorded 
(encapsulated) events to the recipient's parent.

To send a recorded event to a visible object's children use the message 
MSG_VIS_SEND_TO_CHILDREN. The recorded event will not be allowed to 
return anything for the same reason the @visChildren macro can not.

n	MSG_VIS_CALL_PARENT

void	MSG_VIS_CALL_PARENT(

	EventHandle event);

This message delivers the passed recorded event to the parent of the 
recipient object. It acts as a call, executing immediately even across threads. 

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	event	The event handle of the prerecorded event to be 
delivered.

Return:	Nothing.

Interception:	Unlikely.

Tips:	In Goc, an object should not send this message to itself; instead, it 
should use the @visParent macro described above.

n	MSG_VIS_SEND_TO_PARENT

void	MSG_VIS_SEND_TO_PARENT(

	EventHandle event);

This message delivers the passed recorded event to the parent of the 
recipient object. It acts as a send, allowing the caller to continue execution 
without waiting for the event to be handled.

Source:	Unrestricted.

Destination:	Any visible object.

Parameters:	event	The event handle of the recorded event to be 
delivered.

Return:	Nothing.

Interception:	Unlikely.

Tips:	In Goc, an object should not send this message to itself; instead, it 
should use the @visParent macro described above.

n	MSG_VIS_SEND_TO_CHILDREN

void	MSG_VIS_SEND_TO_CHILDREN(

	EventHandle event);

This message delivers the passed recorded event to each of the recipient's 
children. It acts as a message send and can not return values; there is no way 
for a single message to call several objects and return values from each with 
a single call.

Source:	Unrestricted.

Destination:	Any visible composite object.

Parameters:	event	The event handle of the recorded event to be 
delivered.

Return:	Nothing.

Structures:	In Goc, an object should not send this message to itself; instead, it 
should use the @visChildren macro described above.

Warnings:	Do not pass pointers in the recorded event's parameters because the 
message may not be handled before the pointers are invalidated.

	23.5.4.2	Sending Classed Events Up the Tree

MSG_VIS_VUP_FIND_OBJECT_OF_CLASS, 
MSG_VIS_VUP_CALL_OBJECT_OF_CLASS, 
MSG_VIS_VUP_SEND_TO_OBJECT_OF_CLASS, 
MSG_VIS_VUP_TEST_FOR_OBJECT_OF_CLASS

VisClass has several messages that automatically travel up the visible 
object tree until they get to an object that meets the proper criteria; they then 
deliver themselves to that object. This is accomplished by the default handler 
in VisClass recognizing whether the given object meets the criteria; if it does 
not, the handler passes the message up to the object's parent.

To find an object of a given class in the tree, use the message 
MSG_VIS_VUP_FIND_OBJECT_OF_CLASS. This message travels up the tree 
starting at the recipient until it reaches the first object of that class. So if you 
are looking for an object of VisCompClass, at the most the message will be 
passed up a single level.

If you need to send a message to an object of a given class in the visible tree, 
you can either find it and send it the message or send the message directly 
with the visible upward messages MSG_VIS_VUP_CALL_OBJECT_OF_CLASS 
and MSG_VIS_VUP_SEND_TO_OBJECT_OF_CLASS. These messages search 
up the tree in the same was as MSG_VIS_VUP_FIND_OBJECT_OF_CLASS, and 
they then deliver the passed event to the resulting object. 

To see simply whether an object of a given class exists in the visible tree, use 
MSG_VIS_VUP_TEST_FOR_OBJECT_OF_CLASS. This is useful if you are going 
to use MSG_VIS_VUP_CALL_OBJECT_OF_CLASS (or its counterpart). If no 
object of the given class exists, you can skip sending the recorded message.

To send classed messages to an object in the tree that is of a specific class, you 
can use TravelOption with certain MetaClass messages. VisClass defines 
a travel option TO_VIS_PARENT, which sends the message to the first object 
up the tree that is of the specified class.

n	MSG_VIS_VUP_FIND_OBJECT_OF_CLASS

optr	MSG_VIS_VUP_FIND_OBJECT_OF_CLASS(

	ClassStruct *class);

This message searches up the visible object tree until it encounters an object 
of the specified class. It then returns the optr of that object.

Source:	Unrestricted.

Destination:	Any visible object-typically sent by a visible object to itself to find an 
object of the given class above it in the visible object tree.

Parameters:	class	A pointer to the ClassStruct structure of the class 
to be searched for.

Return:	The optr of the object of the passed class. If multiple objects of this class 
exist in the tree, the first encountered will be returned. If no objects of 
this class are in the tree, a NullOptr will be returned.

Interception:	Unlikely-only objects that masquerade as objects of a different class 
would subclass this message. This practice is highly discouraged.

n	MSG_VIS_VUP_TEST_FOR_OBJECT_OF_CLASS

Boolean	MSG_VIS_VUP_TEST_FOR_OBJECT_OF_CLASS(

	ClassStruct *class);

This message searches up the visible tree and determines whether an object 
of the given class is in the tree.

Source:	Unrestricted.

Destination:	Any visible object-typically sent before 
MSG_VIS_VUP_CALL_OBJECT_OF_CLASS or 
MSG_VIS_VUP_SEND_TO_OBJECT_OF_CLASS to ensure that a 
recipient for the message exists.

Parameters:	class	A pointer to the ClassStruct structure of the class 
to be searched for.

Return:	True if the class is found; false if it is not.

Interception:	Unlikely.

n	MSG_VIS_VUP_CALL_OBJECT_OF_CLASS

void	MSG_VIS_VUP_CALL_OBJECT_OF_CLASS(

	EventHandle event);

This message searches up the visible tree until it encounters an object of the 
proper class for the recorded event. The class is specified within the passed 
event. When the first such object is found, it will be called with the classed 
event as if an @call had been used with the event directly.

Source:	Unrestricted.

Destination:	Any visible object-The passed event will be delivered to the first object 
of the appropriate class, not necessarily to the recipient of the 
MSG_VIS_VUP_CALL_OBJECT_OF_CLASS.

Parameters:	event	The event handle of a recorded event.

Return:	The classed event delivered by this message may return values as 
determined by the event. This message returns nothing.

Interception:	Unlikely.

n	MSG_VIS_VUP_SEND_TO_OBJECT_OF_CLASS

void	MSG_VIS_VUP_SEND_TO_OBJECT_OF_CLASS(

	EventHandle event);

This message searches up the visible tree until it encounters an object of the 
proper class for the recorded event. The class is specified within the passed 
event. When the first such object is found, the message will be delivered to 
that object as if an @send had been used with the event directly.

Source:	Unrestricted.

Destination:	Any visible object-The passed event will be delivered to the first object 
of the appropriate class, not necessarily to the object that received the 
MSG_VIS_VUP_SEND_TO_OBJECT_OF_CLASS.

Parameters:	event	The event handle of a recorded event.

Return:	Nothing. The recorded event may not return anything.

Interception:	Unlikely.

Warnings:	The recorded event should not pass pointers among its parameters.

	23.5.4.3	Visible Upward Queries

MSG_VIS_VUP_QUERY

You can create your own messages that get passed up the visible tree by 
creating aliases of MSG_VIS_VUP_QUERY. MSG_VIS_VUP_QUERY, by itself, 
does nothing useful; it simply gets passed up the visible tree without ever 
being handled.

You can create your own visible queries to return different types of values 
from objects higher up in the object tree. Take, for example, a music-teaching 
application which uses note objects as distant children of a sheet music 
object. If the note objects needed to know what key they were supposed to be 
in, they would query up the tree with a special upward query message. If we 
assume the sheet music object kept this information, it would want to 
respond to the query message with the appropriate value. Thus, the sheet 
music class would have a line similar to the following:

@alias(MSG_VIS_VUP_QUERY_MUSIC_KEY)
        MusicKeyType MSG_VIS_VUP_QUERY();

This line creates an alias for the general-purpose upward query. The sheet 
music object should have a handler for MSG_VIS_VUP_QUERY_MUSIC_KEY 
in which it figures out and returns the appropriate key. This type of upward 
query can be invaluable in many different situations.

n	MSG_VIS_VUP_QUERY

void	MSG_VIS_VUP_QUERY();

This message simply queries up the tree until it is handled. It is extensible 
so visible objects can implement their own upward queries without adding 
handlers to every class in between it and the query handler.

It is extremely rare that any object would send or handle 
MSG_VIS_VUP_QUERY on its own; many classes, however, may alias this 
message and create their own versions of the upward query.

Source:	Unrestricted-see note above.

Destination:	Any visible object-see note above. Typically sent by a visible object 
either to itself or directly to its visible parent.

Parameters:	None-an alias of this message may have parameters.

Return:	Nothing-an alias of this message may have return values.

Interception:	MSG_VIS_VUP_QUERY itself should not be intercepted. Its aliases, 
however, should be intercepted by the appropriate classes that will 
handle them.

	23.5.4.4	Sending Messages to Window Groups

MSG_VIS_VUP_CALL_WIN_GROUP, MSG_VIS_VUP_SEND_TO_WIN_GROUP

VisClass offers two specific messages for contacting window group objects in 
a visible tree. These are similar to MSG_VIS_VUP_CALL_OBJECT_OF_CLASS 
and MSG_VIS_VUP_SEND_TO_OBJECT_OF_CLASS, except they find the 
window group of the recipient and deliver the event to the window object. 
These two messages are detailed below.

n	MSG_VIS_VUP_CALL_WIN_GROUP

void	MSG_VIS_VUP_CALL_WIN_GROUP(

	EventHandle event);

This message searches up the visible object tree until it encounters a window 
group object. When the first window group is found, it will be called with the 
classed event as if an @call had been used.

Source:	Unrestricted-typically sent by a visible object to itself to deliver the 
event to its window.

Destination:	Any visible object-the passed event will be delivered to a window 
object, not necessarily to the object that receives the 
MSG_VIS_VUP_CALL_WIN_GROUP.

Parameters:	event	The event handle of a recorded event to be 
delivered to the window object.

Return:	The passed event may return its own values, but 
MSG_VIS_VUP_CALL_WIN_GROUP returns nothing.

Interception:	Unlikely.

See Also:	MSG_VIS_VUP_CALL_OBJECT_OF_CLASS.

n	MSG_VIS_VIS_SEND_TO_WIN_GROUP

void	MSG_VIS_VIS_SEND_TO_WIN_GROUP(

	EventHandle event);

This message searches up the visible object tree until it encounters a window 
group object. When the first window group is found, the passed event will be 
delivered to that object as if an @send had been used directly.

Source:	Unrestricted-typically sent by a visible object to itself to deliver the 
event to its window.

Destination:	Any visible object-the passed event will be delivered to a window 
object, not necessarily to the object that receives the 
MSG_VIS_VUP_CALL_WIN_GROUP.

Parameters:	event	The event handle of a recorded event to be 
delivered to the window object.

Return:	Nothing. The recorded event may not return values.

Interception:	Unlikely.

Warnings:	The recorded event may not pass pointers among its parameters.

See Also:	MSG_VIS_VUP_SEND_TO_OBJECT_OF_CLASS.

	23.5.5	Visible Object Window Operations

MSG_VIS_OPEN_WIN, MSG_VIS_CLOSE_WIN, 
MSG_VIS_WIN_ABOUT_TO_BE_CLOSED, MSG_VIS_MOVE_RESIZE_WIN

Typically, windows will be managed entirely by generic UI objects and the 
Specific UI library currently in use. You can, however, manage your own 
VisClass-based window objects by using messages normally used only by 
Specific UI objects. This is a difficult and complex task, however, and it is not 
recommended. The four messages used for this purpose are detailed below.

n	MSG_VIS_OPEN_WIN

void	MSG_VIS_OPEN_WIN(

	WindowHandle parentWindow);

This message is sent to a window or portal object to open its window. The 
graphics window will be opened and drawn on the screen, and a visual 
update will propagate down the displayed visible tree.

Source:	Visual update mechanism.

Destination:	A window group (VTF_IS_WINDOW) or portal (VTF_IS_PORTAL) object.

Parameters:	parentWindow	The window handle of the open window in which 
the new window will be created.

Return:	Nothing.

Interception:	The window group or portal must intercept in order to open the new 
graphics window and set initial parameters (VCI_window).

n	MSG_VIS_CLOSE_WIN

void	MSG_VIS_CLOSE_WIN();

This message is sent to a window or portal object that has its graphics 
window currently on the screen. The window and its visible branch will be 
closed (taken off the screen).

Source:	Visual update mechanism.

Destination:	A window group (VTF_IS_WINDOW) or portal (VTF_IS_PORTAL) object.

Interception:	The window group or portal may intercept if more needs to be done 
than simply closing the graphics window.

n	MSG_VIS_WIN_ABOUT_TO_BE_CLOSED

void	MSG_VIS_WIN_ABOUT_TO_BE_CLOSED();

This message notifies the recipient that the window it's displayed in is about 
to be closed. The default handler for this will remove the visible branch of the 
window off the screen so no redraws will occur before the window closes.

Source:	Visual update mechanism.

Destination:	The window group (VTF_IS_WINDOW) or portal (VTF_IS_PORTAL) 
object that is being closed; the message will then propagate down the 
visible tree.

Interception:	May be intercepted by either the window group or the VisContent 
object if the default behavior is not appropriate for the object.

n	MSG_VIS_MOVE_RESIZE_WIN

void	MSG_VIS_MOVE_RESIZE_WIN();

This message causes the window object to move and/or resize itself based on 
the bounds of its content object. This message is used only by window or 
portal objects and is rarely, if ever, used by objects in your applications.

Source:	Part of the visual update mechanism-typically called by the window 
object on itself in its MSG_VIS_UPDATE_WINDOWS_AND_IMAGE 
handler.

Destination:	The window group (VTF_IS_WINDOW) or portal (VTF_IS_PORTAL) 
object to be resized or moved.

Interception:	The window object may intercept if it does not want to resize to the 
bounds of its content object.

	23.6	Visible Layers and 32-Bit 
Graphics

MSG_VIS_LAYER_SET_DOC_BOUNDS, 
MSG_VIS_LAYER_GET_DOC_BOUNDS, 
MSG_VIS_LAYER_INSERT_OR_DELETE_SPACE

The GEOS graphic space is built on a basis of 16-bit coordinates. A few 
applications, however, will require much more space for their documents. 
GEOS also supports the special use of 32-bit coordinates; applications using 
these coordinates are said to be using the "large document" model.

The visible object library was originally designed with 16-bit coordinates in 
the default GEOS graphics space. All instance data, message parameters and 
return values, and coordinates are assumed to be word-sized integers. A 
large-document visible object library is not provided primarily because there 
is no single visible model that works well with large coordinates, and also 
because no single large model works efficiently for all applications.

It is possible, however, for applications to subclass the standard visible 
classes in order to get them to support the large document model. In order to 
do this, however, you must understand the basic issues involved with the 
large model and with using 32-bit coordinates.

As the application developer, you should read the following sections if you 
will be using the large document model. Each one deals with a different 
problem facing applications that want large documents.

In addition, some complex applications may offer several different visible 
layers in the program. For example, a spreadsheet might want to include a 
graphic object layer for graphics and charts. The content object of the visible 
tree can be set up to have several different children, each of which is a "layer" 
that manages its own objects in the window.

The content in charge of the layers must occasionally set and retrieve the 
document bounds of its children. For example, if the user wants to set the 
page size of the spreadsheet that has a graphical layer, the content object 
must set the new size for all its children. To retrieve the current document 
bounds of a particular object, send it a MSG_VIS_LAYER_GET_DOC_BOUNDS. 
To set the document bounds, send a MSG_VIS_LAYER_SET_DOC_BOUNDS. In 
addition, the application may add or delete space into a layer with 
MSG_VIS_LAYER_INSERT_OR_DELETE_SPACE; for example, if a spreadsheet 
needs to resize a column, it must send this message to the graphic layer to 
ensure the layers handle the sizing properly.

n	MSG_VIS_LAYER_SET_DOC_BOUNDS

void	MSG_VIS_LAYER_SET_DOC_BOUNDS(@stack

	sdword	bottom,

	sdword	right,

	sdword	top,

	sdword	left);

This message sets the 32-bit document bounds for a particular layer object. 
This message is typically sent by a VisContent object to its children, which 
are assumed to be layer objects.

Source:	Unrestricted-typically sent by a VisContent to its large children.

Destination:	Any large (32-bit) visible object or composite.

Parameters:	all	The four parameters describe the new bounds of 
the large document. Since layer objects typically 
cover the entire document, the layer object will set 
its bounds to these values.

Return:	Nothing.

Interception:	All layer objects and large objects must subclass this message. There is 
no default handler.

n	MSG_VIS_LAYER_GET_DOC_BOUNDS

void	MSG_VIS_LAYER_GET_DOC_BOUNDS(

	RectDWord *bounds);

This message returns the 32-bit document bounds of a particular large 
visible object. Typically, a VisContent will query its large children with this 
message when it needs to know their bounds.

Source:	Unrestricted-typically sent by a VisContent to its large children.

Destination:	Any large (32-bit) visible object or composite.

Parameters:	bounds	A pointer to an empty RectDWord structure that 
describes a set of large bounds.

Return:	The pointer to the filled RectDWord structure. The structure should, 
upon return, contain the 32-bit bounds of the large visible object.

Interception:	All layer objects and large objects must subclass this message. There is 
no default handler.

Structures:	The RectDWord structure is show below for convenience:

typedef struct {
    sdword   RD_left;
    sdword   RD_top;
    sdword   RD_right;
    sdword   RD_bottom;
} RectDWord;

n	MSG_VIS_LAYER_INSERT_OR_DELETE_SPACE

void	MSG_VIS_LAYER_INSERT_OR_DELETE_SPACE()

This message should be sent by one layer to another when it changes sizes. 
An example would be a spreadsheet application with a graphic layer; when a 
column in the spreadsheet resizes, the graphic layer must resize accordingly.

Source:	Any visible layer object.

Destination:	The visible layer object requiring resizing.

Parameters:	None.

Return:	Nothing.

Interception:	This message must be intercepted; it has no default behavior.

	23.6.1	Using Visible Document Layers

The first issue with large documents is the basic structure of the visible tree. 
The topmost object of a large visible tree must be able to keep track of 
information about the current translations and coordinates being used. 
Typically, the topmost object would be a subclass of VisContentClass; this 
does not change with large trees, though another consideration has to be 
taken care of.

A content object should not contain any information about the document 
itself; the content object should not be stored along with other document 
information. Thus, the object that acts as the content can not be the object 
that also manages the 32-bit document space. Instead, it is easiest to use a 
VisCompClass object to manage the document space and to place this object 
as a child of the content.

In addition, you can set up several different composite children of the 
content, each one managing its own large document space. Each one of these 
composites is called a "layer object" and manages a "layer" of the document. 
This way, you can have several different layers (such as a spreadsheet layer 
and a graphic layer) in the same document. The layer object should manage 
the calculations and translations necessary for supporting the large 
document space.

	23.6.2	Using 16-Bit Drawing Commands

All the GEOS drawing commands are based on 16-bit coordinates. Drawing 
may only occur within a 16-bit graphics space. The graphics system does, 
however, support extended translations of the 16-bit graphics space within 
32-bit coordinates.

This means that you can think of the large document space as a number of 
smaller, 16-bit "local" graphics spaces. When you need to draw anything, you 
first use an extended translation to get near your drawing point in the large 
document. Then you can draw using 16-bit offsets from the point to which you 
translated. This is illustrated in Figure 23-5.

The application using the extended translation can do so in two different 
ways: It can store a 32-bit translation with each visible object, or it can store 
a 32-bit translation in a visible composite, thereby making the entire visible 
branch under the composite in a 32-bit graphics space. Visible trees 
implementing layer objects must use the second option; the layer must 
contain the translation for the entire visible branch that it manages. If a 
simple large visible tree does not need layers, it may wish to use the first 
solution.

The first of the two solutions is simple but takes up additional memory and 
time; each object, when it draws, must translate the coordinates, draw, then 
translate back. Two translations for each object could significantly affect 
drawing performance unless visual updates are handled carefully.

The other solution, storing a translation in the composite object, requires just 
two translations for the entire branch headed by the composite. Whenever 
the composite receives MSG_VIS_DRAW or MSG_VIS_VUP_CREATE_GSTATE, 
it executes the translation on the GState. As long as the translation is always 
relative to the GState's current transformation (done using 
GrApplyTranslationDWord()), and as long as the translation is undone 
before the GState is returned to the caller, drawing will be done properly.

	23.6.3	The 16-Bit Limit on Visual Bounds

Individual visual objects have 16-bit bounds. If the rules of drawing in the 
32-bit graphics space are followed, this is not a problem. Individual objects 
are constrained to 16-bit width and 16-bit height, however.

The only objects for which having 16-bit bounds is a problem are the tree's 
content object and all the layer objects. This is because these two types of 
objects must have width and height greater than 16 bits. This problem is 
handled differently for each object:

For the content object, the VI_bounds field is set to all zeros and is not used. 
Normally, the content uses its bounds to set the document size in the 
GenView; the responsibility for setting the GenView's document size then 
falls to the application.

For the layer object, the VI_bounds field is set to all zeros and is not used. If 
the bounds of the layer object are important to the application, the layer 
object must be given new instance fields to hold the 32-bit coordinates of the 
bounds. If not, nothing needs to be done; the bounds can simply be ignored.

	23.6.4	Handling MSG_VIS_DRAW

In normal-sized visible trees, MSG_VIS_DRAW gets sent to all objects in the 
tree. This draws the entire visible tree, no matter what portions are visible 
on the screen. For large documents, this can quickly get unwieldy and 
inefficient.

A better solution is for the layer object of each particular layer to intercept 
MSG_VIS_DRAW and pass it on only to those objects in the affected portion of 
the document. For this to work, of course, the layer object must know 
something of the structure and composition of the visible branch below it. 
This is the primary reason the visible object library does not offer a standard 
visible layer class-in essence, it must be defined specifically for each 
application.

	23.6.5	Managing 32-Bit Geometry

Because visible objects and composites maintain their 16-bit bounds in a 
large document, they can still use the 16-bit geometry manager. Layer 
objects, however, can not use the geometry manager. All geometry 
management on the layer level (child positioning, resizing, etc.) must be done 
by the layer object itself in conjunction with its child composites.

	23.6.6	Handling Mouse Events

The GenView is built to support large documents, though its default is 
normal-sized documents. Thus, you can request the view to send large mouse 
events, which carry with them 32 bits of integer and 16 bits of fraction in each 
dimension. The visible classes have no default handlers for these messages, 
so your own classes will have to handle them appropriately.

The large mouse events are the equivalent of their 16-bit counterparts. They 
just carry different data to represent the coordinates of the pointer. All the 
mouse events, both large and normal, are described in "Input," Chapter 11 of 
the Concepts Book.

Normal composite objects will not be affected by large mouse events; the 
composite will continue to send the event on to the proper child as if it were 
in a 16-bit document. Layer and content objects, however, must process these 
messages differently.

If no object within the visible tree has the mouse grabbed, the content of the 
tree must decide which layer object should receive the mouse events. How the 
content and layer objects negotiate this is up to the particular application; 
some applications may consider that one layer is "on top of" the others, and 
other applications may determine which layer is the most appropriate based 
on the event context. By default, the large mouse events are passed by 
VisContentClass straight on to the first layer child. If you want a more 
complex scheme, you will have to subclass VisContentClass and intercept 
these messages.

	23.6.7	Setting Up the Objects

Finally, you should be aware of what attributes to set in both the GenView 
and the VisContent objects of your visible tree to support the large document. 
You could easily find this out by looking through the various attributes of 
those classes (and you are encouraged to do so), but the following guide is 
provided for convenience:

In the GenView object, set GVA_WINDOW_COORDINATE_MOUSE_EVENTS in 
the GVI_attrs instance data field. This will pass mouse events in terms of 
offsets from the upper-left corner of the view window rather than in absolute 
document coordinates. VisContentClass handles these events and 
automatically turns them into document coordinates.

In the VisContent, set VCNA_WINDOW_COORDINATE_MOUSE_EVENTS and 
VCNA_LARGE_DOCUMENT_MODEL in the VCNI_attrs field. The first of these 
tells the content that it will receive input events in window coordinates 
rather than in document coordinates. The second will have the effect of 
making the content object ignore its bounds field and geometry management. 
It will also tell the content that all its children are layer objects. Setting the 
large document model will cause the content to send all the following 
messages on to all its children rather than handle them directly: 
MSG_VIS_DRAW, MSG_VIS_CONTENT_VIEW_ORIGIN_CHANGED, 
MSG_VIS_CONTENT_VIEW_SCALE_FACTOR_CHANGED, and 
MSG_VIS_CONTENT_VIEW_SIZE_CHANGED.

You do not have to create all the objects you may need; be aware that the 
Graphic Object Library provides its own layer object that supports a 32-bit 
graphic object layer. The spreadsheet object also exports its own layer object.

	23.6.7.1	Requirements of Layer Objects

Layer objects will need to handle MSG_VIS_LAYER_SET_DOC_BOUNDS, 
which will be sent to all layers when the document bounds change.

In essence the layer object's job is to isolate its children and their children 
from the fact that they are in a 32-bit document rather than a 16-bit 
document. In order to do this, layer objects must do several things:

u	Store the translation
This is a set of 32-bit translation offsets. These offsets represent the 
current location, if any, where the layer is being drawn in the 32-bit 
coordinate space.

u	Intercept MSG_VIS_DRAW
In its handler, the layer should apply any 32-bit translations (using 
GrApplyTranslationDWord()) on the GState provided by 
MSG_VIS_DRAW. It should then intelligently select which of its children 
are affected by the drawing event and pass the message on to them with 
the translated GState. The handler should then untranslate the GState 
before returning.

u	Intercept MSG_VIS_VUP_CREATE_GSTATE
In the handler, the layer must first call its superclass (to create the 
GState normally), then apply the necessary translation using 
GrApplyTranslationDWord(). It can then return the translated 
GState.

u	Intercept and handle large mouse events
Each large mouse event that may be interesting to the layer must be 
handled by the layer object. This is to ensure that mouse events that 
occur when no object has the mouse grab get handled. If the layer has 
16-bit visible children, it should translate the mouse event into small 
mouse events before passing it to its superclass. If the layer has 32-bit 
visible children, it should first translate both mouse coordinates and then 
decide which of its large children should receive the event.

	23.6.7.2	Requirements of 32-bit Visible Objects

Large visible objects in the visible tree should be equipped to handle both 
large and small mouse events. This is because the parent object may have 
both 32-bit and 16-bit children. If it does, it will have to send out only small 
mouse events; otherwise, the 16-bit objects would be confused by the large 
mouse events.

	23.6.7.3	Requirements of 16-bit Visible Objects

Because 16-bit objects are the norm and not the exception, there are few 
requirements for them. However, 16-bit objects in 32-bit documents must do 
one thing: they must prevent the system from allowing the user to select the 
object and then drag-scroll too far. To prevent this from happening, the 
visible object must call MSG_VIS_VUP_SET_MOUSE_INTERACTION_BOUNDS 
to set a temporary boundary on drag scrolling.

	23.7	VisClass Error Checking

MSG_VIS_VUP_EC_ENSURE_WINDOW_NOT_REFERENCED, 
MSG_VIS_VUP_EC_ENSURE_OBJ_BLOCK_NOT_REFERENCED, 
MSG_VIS_VUP_EC_ENSURE_OD_NOT_REFERENCED

VisClass provides three messages you can use for special error checking. 
These three messages are provided especially to make sure that all objects 
being destroyed or removed will be destroyed cleanly. The default handlers 
for these messages should cause a fatal error if their criteria are not met.

n	MSG_VIS_VUP_EC_ENSURE_WINDOW_NOT_REFERENCED

void	MSG_VIS_VUP_EC_ENSURE_WINDOW_NOT_REFERENCED(

	WindowHandle window);

This message travels up the visible object tree, ensuring that the window 
handle passed is not stored anywhere that it might cause trouble. This 
message may be used when a window is being destroyed and its handle is 
about to be freed.

Source:	Unrestricted.

Destination:	Any visible object in the affected visible tree.

Parameters:	window	The handle of the window being destroyed.

Return:	Nothing-if it returns, no error was encountered.

Interception:	Do not intercept this message.

n	MSG_VIS_VUP_EC_ENSURE_OBJ_BLOCK_NOT_REFERENCED

void	MSG_VIS_VUP_EC_ENSURE_OBJ_BLOCK_NOT_REFERENCED(

	MemHandle objBlock);

This message travels up the visible object tree, ensuring that the memory 
handle (the handle of an object block) passed is not stored anywhere that it 
might cause trouble. This message may be used just before the object block's 
handle is freed to ensure that no stale references will remain.

Source:	Unrestricted.

Destination:	Any visible object in the affected visible tree.

Parameters:	objBlock	The handle of the block being freed.

Return:	Nothing-if it returns, no error was encountered.

Interception:	Do not intercept this message.

n	MSG_VIS_VUP_EC_ENSURE_OD_NOT_REFERENCED

void	MSG_VIS_VUP_EC_ENSURE_OD_NOT_REFERENCED(

	optr	object);

This message travels up the visible object tree, ensuring that the optr passed 
is not stored by any objects in the tree. This message may be sent when the 
object is being destroyed; any objects methods encountering a match between 
a stored optr and the passed optr should force a fatal error.

Source:	Unrestricted.

Destination:	Any visible object in the affected visible tree.

Parameters:	object	The handle of the object being destroyed.

Return:	Nothing-if it returns, no error was encountered.

Interception:	Do not intercept this message.

	23.8	Creating Specific UIs

It is possible, using visible object classes, to create your own specific UIs. It is 
a complex and difficult task, however, and only very few developers will 
expect to do this. Documentation on creating a custom specific UI may appear 
either in a future release of this documentation or under separate cover. 
Contact Geoworks Developer Products for more information.

	23.9	Basic Summary

Visible objects are involved in several basic operations, each of which has its 
own primary messages:

u	Drawing
Vis objects must handle MSG_VIS_DRAW (page 1322) if they are to draw 
after their window has been exposed. Objects wishing to redraw 
themselves outside of exposure events can call 
MSG_VIS_VUP_CREATE_GSTATE (page 1319) to create a GState in their 
view windows for drawing.

u	Being added to an object tree
When an object is added to a visible tree, it must then force a redraw of 
the tree. It can be added to the tree with MSG_VIS_ADD_CHILD (page 
1377), and the tree can be updated with 
MSG_VIS_VUP_UPDATE_WIN_GROUP (page 1327).

u	Being removed from an object tree
A visible object may be removed from a visible tree with 
MSG_VIS_REMOVE (page 1378). This message will close the object (take 
it off the screen) and then segregate it from its parent.

u	Undergoing visual update
The visual update mechanism is automatic for the most part. An object 
that requires visual update, however, can use MSG_VIS_MARK_INVALID 
(page 1325) in conjunction with MSG_VIS_VUP_UPDATE_WIN_GROUP 
(page 1327) to cause the update.

u	Geometry management
Geometry management of visible objects can be as simple as setting a few 
flags in the instance data or as complex as manually setting position and 
size of the objects. For a full description of geometry management of 
visible objects, see "Positioning Visible Objects" on page 1338.

u	Being Destroyed
Visible objects may be destroyed even when they are part of a visible tree 
that is on the screen. MSG_VIS_DESTROY (page 1374) first removes the 
object from the tree (with MSG_VIS_REMOVE) and then destroys it 
(through the MetaClass detach and destroy mechanisms).
