Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Legacy Legacy Mac OS X Reference Library Mac OS 8 and 9 Developer Documentation


Defining Your Own Control Definition Function

A control definition function determines how a control generally looks and behaves. Various Control Manager functions call a control definition function whenever they need to perform a control-dependent action, such as drawing the control on the screen. In addition to standard control definition functions, defined by the system, you can make your own custom control definition functions.

The Control Manager calls the Resource Manager to access a control definition function with the given resource ID; for a description of how to derive a control definition function ID, see Control Definition IDs . The Resource Manager reads a control definition function into memory and returns a handle to it. The Control Manager stores this handle in the contrlDefProc field of the control structure.

When various Control Manager functions need to perform a type-dependent action on the control, they call the control definition function and pass it the variation code for its type as a parameter. You can define your own variation codes; this allows you to use one 'CDEF' resource to handle several variations of the same general control. see 'CNTL' for further discussion of controls, their resources, and their IDs.

If you choose to provide your own control definition functions, these functions should apply the user's desktop color choices the same way the standard control definition functions do. You can use control color tables of any desired size and define their contents in any way you wish, except that part indices and messages 0 through 127 are reserved for system definition.

The following Control Manager function for defining your own control definition function is changed with Appearance Manager 1.0:


MyControlDefProc

If you wish to define new, nonstandard controls for your application, you must write a control definition function and store it in a resource file as a resource of type 'CDEF' .

The Control Manager declares the type for an application-defined control definition function as follows:

typedef pascal SInt32 (*ControlDefProcPtr)(
                     SInt16 varCode,
                     ControlHandle theControl,
                     ControlDefProcMessage message,
                     SInt32 param);

The Control Manager defines the data type ControlDefUPP to identify the universal procedure pointer for this application-defined function:

typedef UniversalProcPtr ControlDefUPP;

You typically use the NewControlDefProc macro like this:

ControlDefUPP myControlDefUPP;
myControlDefUPP = NewControlDefProc (MyControl);

You typically use the CallControlDefProc macro like this:

CallControlDefProc(myControlDefUPP, varCode, theControl, message, param);

Here's how to declare the function MyControlDefProc :

pascal SInt32 MyControlDefProc (
                     SInt16 varCode,
                     ControlHandle theControl,
                     ControlDefProcMessage message,
                     SInt32 param);
varCode
The control's variation code.
theControl
A handle to the control that the operation will affect.
message
A code for the task to be performed. The message parameter contains one of the task codes defined in Messages . The subsections that follow explain each of these tasks in detail.
param
Data associated with the task specified by the message parameter. If the task requires no data, this parameter is ignored.
function result
The function results that your control definition function returns depend on the value that the Control Manager passes in the message parameter.

DISCUSSION

The Control Manager calls your control definition function under various circumstances; the Control Manager uses the message parameter to inform your control definition function what action it must perform. The data that the Control Manager passes in the param parameter, the action that your control definition function must undertake, and the function results that your control definition function returns all depend on the value that the Control Manager passes in the message parameter. The rest of this section describes how to respond to the various values that the Control Manager passes in the message parameter.


VERSION NOTES

Changed with Appearance Manager 1.0 to support new control definition messages.


Messages

The Control Manager passes constants of type ControlDefProcMessage to indicate the action your control definition function must perform.

enum {
    drawCntl                    = 0,
    testCntl                    = 1,
    calcCRgns                   = 2,
    initCntl                    = 3,
    dispCntl                    = 4,
    posCntl                     = 5,
    thumbCntl                   = 6,
    dragCntl                    = 7,
    autoTrack                   = 8,
    calcCntlRgn                 = 10,
    calcThumbRgn                = 11,
    kControlMsgDrawGhost        = 13,
    kControlMsgCalcBestRect     = 14,
    kControlMsgHandleTracking   = 15,
    kControlMsgFocus            = 16,
    kControlMsgKeyDown          = 17,
    kControlMsgIdle             = 18,
    kControlMsgGetFeatures      = 19,
    kControlMsgSetData          = 20,
    kControlMsgGetData          = 21,
    kControlMsgActivate         = 22,
    kControlMsgSetUpBackground  = 23,
    kControlMsgSubValueChanged  = 25,
    kControlMsgCalcValueFromPos = 26,
    kControlMsgTestNewMsgSupport= 27,
    kControlMsgSubControlAdded  = 28,
    kControlMsgSubControlRemoved= 29
};
typedef SInt16 ControlDefProcMessage;


Constant descriptions

drawCntl
Draw the entire control or part of a control.
testCntl
Test where the mouse has been pressed.
calcCRgns
Calculate the region for the control or the indicator in 24-bit systems. This message is obsolete in Mac OS 7.6 and later.
initCntl
Perform additional control initialization.
dispCntl
Perform additional control disposal actions.
posCntl
Move and update the indicator setting.
thumbCntl
Calculate the parameters for dragging the indicator.
dragCntl
Perform customized dragging (of the control or its indicator).
autoTrack
Execute the specified action function.
calcCntlRgn
Calculate the control region in 32-bit systems.
calcThumbRgn
Calculate the indicator region in 32-bit systems.
kControlMsgDrawGhost
Draw a ghost image of the indicator. Available with Appearance Manager 1.0 and later.
kControlMsgCalcBestRect
Calculate the optimal control rectangle. Available with Appearance Manager 1.0 and later.
kControlMsgHandleTracking
Perform custom tracking. Available with Appearance Manager 1.0 and later.
kControlMsgFocus
Handle keyboard focus. Available with Appearance Manager 1.0 and later.
kControlMsgKeyDown
Handle keyboard events. Available with Appearance Manager 1.0 and later.
kControlMsgIdle
Perform idle processing. Available with Appearance Manager 1.0 and later.
kControlMsgGetFeatures
Specify which Appearance-compliant messages are supported. Available with Appearance Manager 1.0 and later.
kControlMsgSetData
Set control-specific data. Available with Appearance Manager 1.0 and later.
kControlMsgGetData
Get control-specific data. Available with Appearance Manager 1.0 and later.
kControlMsgActivate
Handle activate and deactivate events. Available with Appearance Manager 1.0 and later.
kControlMsgSetUpBackground
Set the control's background color or pattern (only available if the control supports embedding). Available with Appearance Manager 1.0 and later.
kControlMsgSubValueChanged
Be informed that the value of a subcontrol embedded in the control has changed; this message is useful for radio groups. Available with Appearance 1.0.1 and later.
kControlMsgCalcValueFromPos
Support live feedback while dragging the indicator and calculate the control value based on the new indicator region. Available with Appearance Manager 1.0 and later.
kControlMsgTestNewMsgSupport
Specify whether Appearance-compliant messages are supported. Available with Appearance Manager 1.0 and later.
kControlMsgSubControlAdded
Be informed that a subcontrol has been embedded in the control. Available with Appearance 1.0.1 and later.
kControlMsgSubControlRemoved
Be informed that a subcontrol is about to be removed from the control. Available with Appearance 1.0.1 and later.

Drawing the Control or Its Part

When the Control Manager passes the value drawCntl in the message parameter, your control definition function should respond by drawing the indicator or the entire control.

The Control Manager passes one of the following drawing constants in the low word of the param parameter to specify whether the user is drawing an indicator or the whole control. The high-order word of the param parameter may contain undefined data; therefore, evaluate only the low-order word of this parameter.

enum {  
    kDrawControlEntireControl   = 0,
    kDrawControlIndicatorOnly   = 129
};


Constant descriptions

kDrawControlEntireControl
Draw the entire control.
kDrawControlIndicatorOnly
Draw the indicator only.

With the exception of part code 128, which is reserved for future use and should not be used, any other value indicates a part code for the control.

If the specified control is visible, your control definition function should draw the control (or the part specified in the param parameter) within the control's rectangle. If the control is invisible (that is, if its contrlVis field is set to 0), your control definition function does nothing.

When drawing the control or its part, take into account the current values of its contrlHilite and contrlValue fields in the control structure.

If the part code for your control's indicator is passed in param , assume that the indicator hasn't moved; the Control Manager, for example, may be calling your control definition function so that you may simply highlight the indicator. However, when your application calls SetControlValue , SetControlMinimum , and SetControlMaximum , they in turn may call your control definition function with the drawCntl message to redraw the indicator. Since these functions have no way of determining what part code you chose for your indicator, they all pass 129 in param , meaning that you should move your indicator. Your control definition function must detect this part code as a special case and remove the indicator from its former location before drawing it. If your control has more than one indicator, you should interpret 129 to mean all indicators.

When sent the message drawCntl , your control definition function should return 0 as its function result.


Testing Where the Mouse-Down Event Occurs

When the Control Manager passes the value for the testCntl constant in the message parameter, your control definition function should respond by determining whether a specified point is in a visible control.

The Control Manager passes a point (in local coordinates) in the param parameter. The point's vertical coordinate is contained in the high-order word of the long integer, and horizontal coordinate is contained in the low-order word.

Your control definition function should return the part code of the part that contains the specified point; it should return 0 if the point is outside the control or if the control is inactive.


Calculating the Control and Indicator Regions on 24-Bit Systems

When the Control Manager passes the value for the calcCRgns constant in the message parameter, your control definition function should calculate the region passed in the param parameter for the specified control or its indicator.

The Control Manager passes a QuickDraw region handle in the param parameter. If the high-order bit of param is set, the region requested is that of the control's indicator; otherwise, the region requested is that of the entire control. Your control definition function should clear the high bit of the region handle before calculating the region.

When passed this message, your control definition function should always return 0, and it should express the region in the local coordinate system of the control's window.


IMPORTANT

The calcCRgns message will never be sent to any system running on 32-bit mode and is therefore obsolete in Mac OS 7.6 and later. The calcCntlRgn and calcThumbRgn messages will be sent instead.


Calculating the Control and Indicator Regions on 32-Bit Systems

When the Control Manager passes the values for the calcCntlRgn or calcThumbRgn constants in the message parameter, your control definition function should calculate the region for the specified control or its indicator using the QuickDraw region handle passed in the param parameter .

If the Control Manager passes the value for the calcThumbRgn constant in the message parameter, calculate the region occupied by the indicator. If the Control Manager passes the value for the calcCntlRgn constant in the message parameter, calculate the region for the entire control.

When passed this message, your control definition function should always return 0, and it should express the region in the local coordinate system of the control's window.


Performing Additional Control Initialization

After initializing fields of a control structure as appropriate when creating a new control, the Control Manager passes initCntl in the message parameter to give your control definition function the opportunity to perform any type-specific initialization you may require. For example, the standard control definition function for scroll bars allocates space for a region to hold the scroll box and stores the region handle in the contrlData field of the new control structure.

When passed the value for the initCntl constant in the message parameter, your control definition function should ignore the param parameter and return 0 as a function result.


Performing Additional Control Disposal Actions

The function DisposeControl passes dispCntl in the message parameter to give your control definition function the opportunity to carry out any additional actions when disposing of a control. For example, the standard definition function for scroll bars releases the memory occupied by the scroll box region, whose handle is kept in the contrlData field of the control structure.

When passed the value for the dispCntl constant in the message parameter, your control definition function should ignore the param parameter and return 0 as a function result.


Dragging the Control or Its Indicator

When a mouse-up event occurs in the indicator of a control, the HandleControlClick or TrackControl functions call your control definition function and pass posCntl in the message parameter. In this case, the Control Manager passes a point (in coordinates local to the control's window) in the param parameter that specifies the vertical and horizontal offset, in pixels, by which your control definition function should move the indicator from its current position. Typically, this is the offset between the points where the cursor was when the user pressed and released the mouse button while dragging the indicator. The point's vertical offset is contained in the high-order word of the param parameter, and its horizontal offset is contained in the low-order word.

Your definition function should calculate the control's new setting based on the given offset and then, to reflect the new setting, redraw the control and update the contrlValue field in the control structure. Your control definition function should ignore the param parameter and return 0 as a function result.


Calculating Parameters for Dragging the Indicator

When the Control Manager passes the value for thumbCntl in the message parameter, your control definition function should respond by calculating values analogous to the limitRect , slopRect , and axis parameters of DragControl that constrain how the indicator is dragged. On entry, the fields param->limitRect.top and param->limitRect.left contain the point where the mouse-down event first occurred.

The Control Manager passes a pointer to a structure of type IndicatorDragConstraint in the param parameter:

struct IndicatorDragConstraint {
    Rect            limitRect;
    Rect            slopRect;
    DragConstraint  axis;
};
typedef struct IndicatorDragConstraint IndicatorDragConstraint;
typedef IndicatorDragConstraint *IndicatorDragConstraintPtr;
typedef IndicatorDragConstraintPtr *IndicatorDragConstraintHandle;
limitRect
A pointer to a rectangle--whose coordinates should normally coincide with or be contained in the window's content region--delimiting the area in which the user can drag the control's outline.
slopRect
A pointer to a rectangle that allows some extra space for the user to move the mouse while still constraining the control within the rectangle specified in the limitRect parameter.
axis
The axis along which the user may drag the control's outline.

Your definition function should store the appropriate values into the fields of the structure pointed to by the param parameter; they're analogous to the similarly named parameters of the Window Manager function DragGrayRgn .

Your control definition function should return 0 as function result.

Performing Custom Dragging

When the Control Manager passes the value for the dragCntl constant in the message parameter, the param parameter typically contains a custom dragging constant with one of the following values to specify whether the user is dragging an indicator or the whole control:

enum {  
    kDragControlEntireControl   = 0,
    kDragControlIndicator       = 1
};


Constant descriptions

kDragControlEntireControl
Dragging the entire control.
kDragControlIndicator
Dragging the indicator.

Note

When the Appearance Manager is present, the message kControlMsgHandleTracking should be sent instead of dragCntl to handle any custom tracking; see Performing Custom Tracking .

If you want to use the Control Manager's default method of dragging, which is to call DragControl to drag the control or the Window Manager function DragGrayRgn to drag its indicator, return 0 as the function result for your control definition function.

If your control definition function returns a nonzero value, your control definition function (not the Control Manager) must drag the specified control (or its indicator) to follow the cursor until the user releases the mouse button. If the user drags the entire control, your definition function should use the function MoveControl to reposition the control to its new location after the user releases the mouse button. If the user drags the indicator, your definition function must calculate the control's new setting (based on the pixel offset between the points where the cursor was when the user pressed and released the mouse button while dragging the indicator) and then, to reflect the new setting, redraw the control and update the contrlValue field in the control structure. Note that, in this case, the functions HandleControlClick and TrackControl return 0 whether or not the user changes the indicator's position. Thus, you must determine whether the user has changed the control's setting by another method, for instance, by comparing the control's value before and after the call to HandleControlClick .


Executing an Action Function

The only way to specify actions in response to all mouse-down events in a control or its indicator is to define your own control definition function that specifies an action function. When you create the control, your control definition function must first respond to the initCntl message by storing (ControlDefUPP)-1L in the contrlAction field of the control structure. (The Control Manager sends the initCntl message to your control definition function after initializing the fields of a new control structure.) Then, when your application passes (ControlActionUPP)-1L in the actionProc parameter of HandleControlClick or TrackControl , HandleControlClick calls your control definition function with the autoTrack message. The Control Manager passes the part code of the part where the mouse-down event occurs in the param parameter. Your control definition function should then use this information to respond as an action function would.

Note

For the autoTrack message, the high-order word of the param parameter may contain undefined data; therefore, evaluate only the low-order word of this parameter.

If the mouse-down event occurs in an indicator of a control that supports live feedback, your action function should take two parameters (a handle to the control and the part code of the control where the mouse-down event first occurred). This action function is the same one you would use to define actions to be performed in control part codes in response to a mouse-down event; see MyActionProc .

If the mouse-down event occurs in an indicator of a control that does not support live feedback, your action function should take no parameters, because the user may move the cursor outside the indicator while dragging it; see MyIndicatorActionProc .


Specifying Whether Appearance-Compliant Messages Are Supported

If your control definition function supports Appearance-compliant messages, it should return kControlSupportsNewMessages as a function result when the Control Manager passes kControlMsgTestNewMsgSupport in the message parameter.

enum{
    kControlSupportsNewMessages = ' ok '
};


Constant description

kControlSupportsNewMessages
The control definition function supports new messages introduced with Mac OS 8 and the Appearance Manager.

Specifying Which Appearance-Compliant Messages Are Supported

If your control definition function supports Appearance-compliant messages, it should return a bit field of the features it supports in response to the kControlMsgGetFeatures message. Your control definition function should ignore the param parameter.

The bit field returned by your control definition function should be composed of one or more of the following bits:

enum{
    kControlSupportsGhosting    = 1 << 0,
    kControlSupportsEmbedding   = 1 << 1,
    kControlSupportsFocus       = 1 << 2,
    kControlWantsIdle           = 1 << 3,
    kControlWantsActivate       = 1 << 4,
    kControlHandlesTracking     = 1 << 5,
    kControlSupportsDataAccess  = 1 << 6,
    kControlHasSpecialBackground= 1 << 7,
    kControlGetsFocusOnClick    = 1 << 8,
    kControlSupportsCalcBestRect= 1 << 9,
    kControlSupportsLiveFeedback= 1 << 10,
    kControlHasRadioBehavior    = 1 << 11
};


Constant descriptions

kControlSupportsGhosting
If this bit (bit 0) is set, the control definition function supports the kControlMsgDrawGhost message.
kControlSupportsEmbedding
If this bit (bit 1) is set, the control definition function supports the kControlMsgSubControlAdded and kControlMsgSubControlRemoved messages.
kControlSupportsFocus
If this bit (bit 2) is set, the control definition function supports the kControlMsgKeyDown message. If this bit and the kControlGetsFocusOnClick bit are set, the control definition function supports the kControlMsgFocus message.
kControlWantsIdle
If this bit (bit 3) is set, the control definition function supports the kControlMsgIdle message.
kControlWantsActivate
If this bit (bit 4) is set, the control definition function supports the kControlMsgActivate message.
kControlHandlesTracking
If this bit (bit 5) is set, the control definition function supports the kControlMsgHandleTracking message.
kControlSupportsDataAccess
If this bit (bit 6) is set, the control definition function supports the kControlMsgGetData and kControlMsgSetData messages.
kControlHasSpecialBackground
If this bit (bit 7) is set, the control definition function supports the kControlMsgSetUpBackground message.
kControlGetsFocusOnClick
If this bit (bit 8) and the kControlSupportsFocus bit are set, the control definition function supports the kControlMsgFocus message.
kControlSupportsCalcBestRect
If this bit (bit 9) is set, the control definition function supports the kControlMsgCalcBestRect message.
kControlSupportsLiveFeedback
If this bit (bit 10) is set, the control definition function supports the kControlMsgCalcValueFromPos message.
kControlHasRadioBehavior
If this bit (bit 11) is set, the control definition function supports radio button behavior and can be embedded in a radio group control. This constant is available with Appearance 1.0.1 and later.

Drawing a Ghost Image of the Indicator

If your control definition function supports indicator ghosting, it should return kControlSupportsGhosting as one of the feature bits in response to a kControlMsgGetFeatures message. If this bit is set and the control indicator is being tracked, the Control Manager calls your control definition function and passes kControlMsgDrawGhost in the message parameter. A handle to the region where the ghost should be drawn will be passed in the param parameter.

Your control definition function should respond by redrawing the control with the ghosted indicator at the specified location and should return 0 as its function result.

Note

The ghost indicator should always be drawn before the actual indicator so that it appears underneath the actual indicator.


Calculating the Optimal Control Rectangle

If your control definition function supports calculating the optimal dimensions of the control rectangle, it should return kControlSupportsCalcBestRect as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set and GetBestControlRect is called, the Control Manager will call your control definition function and pass kControlMsgCalcBestRect in the message parameter. The Control Manager passes a pointer to a control size calculation structure in the param parameter.

Your control definition function should respond by calculating the width and height of the optimal control rectangle and adjusting the rectangle by setting the height and width fields of the control size calculation structure to the appropriate values. If your control definition function displays text, it should pass in the offset from the bottom of control to the base of the text in the baseLine field of the structure. Your control definition function should return the offset value stored in the structure's baseLine field.

The control size calculation structure is a structure of type ControlCalcSizeRec :

struct ControlCalcSizeRec {
    SInt16  height;
    SInt16  width;
    SInt16  baseLine;
};
typedef struct ControlCalcSizeRec ControlCalcSizeRec;
typedef ControlCalcSizeRec *ControlCalcSizePtr;
height
The optimal height (in pixels) of the control's bounding rectangle.
width
The optimal width (in pixels) of the control's bounding rectangle.
baseLine
The offset from the bottom of the control to the base of the text. This value is generally negative.

Performing Custom Tracking

If your control definition function supports custom tracking, it should return kControlHandlesTracking as one of the feature bits in response to a kControlMsgGetFeatures message. If this bit is set and a mouse-down event occurs in your control, TrackControl or HandleControlClick calls your control definition function and passes kControlMsgHandlesTracking in the message parameter. The Control Manager passes a pointer to a control tracking structure in the param parameter. Your control definition function should respond appropriately and return the part code that was hit, or kControlNoPart if the mouse-down event occurred outside the control; see Control Part Code Constants .

The control tracking structure is a structure of type ControlTrackingRec :

struct ControlTrackingRec {
    Point               startPt;
    SInt16              modifiers;
    ControlActionUPP    action;
};
typedef struct ControlTrackingRec ControlTrackingRec;
typedef ControlTrackingRec *ControlTrackingPtr;
startPt
The location of the cursor at the time the mouse button was first pressed, in local coordinates. Your application retrieves this point from the where field of the event structure.
modifiers
The constant in the modifiers field of the event structure specifying the state of the modifier keys and the mouse button at the time the event was posted.
action
A pointer to an action function defining what action your application takes while the user holds down the mouse button. The value of the actionProc parameter can be a valid procPtr , nil , or -1. A value of -1 indicates that the control should either perform auto tracking, or if it is incapable of doing so, do nothing (like nil ).

Handling Keyboard Focus

If your control definition function can change its keyboard focus, it should set kControlSupportsFocus and kControlGetsFocusOnClick as feature bits in response to a kControlMsgGetFeatures message. If these bits are set and the AdvanceKeyboardFocus , ReverseKeyboardFocus , ClearKeyboardFocus , or SetKeyboardFocus function is called, the Control Manager calls your control definition function and passes kControlMsgFocus in the message parameter.

The Control Manager passes one of the control focus part code constants described below or a valid part code in the param parameter. Your control definition function should respond by adjusting the focus accordingly.

Your control definition function should return the control focus part code or actual control part that was focused on. Return kControlFocusNoPart if your control does not accept focus or has just relinquished it. Return a nonzero part code to indicate that your control received keyboard focus. Your control definition function is responsible for maintaining which part is focused.

enum {
    kControlFocusNoPart     = 0,
    kControlFocusNextPart   = -1,
    kControlFocusPrevPart   = -2
};
typedef SInt16 ControlFocusPart;


Constant descriptions

kControlFocusNoPart
Your control definition function should relinquish its focus and return kControlFocusNoPart . It might respond by deactivating its text edit handle and erasing its focus ring. If the control is at the end of its subparts, it should return kControlFocusNoPart . This tells the focusing mechanism to jump to the next control that supports focus.
kControlFocusNextPart
Your control definition function should change keyboard focus to its next part, the entire control, or remove keyboard focus from the control, depending upon the circumstances. For multiple part controls that already had keyboard focus, the next part of the control would receive keyboard focus when kControlFocusNextPart was passed in the param parameter. For example, a clock control with keyboard focus would change its focus to the left-most element of the control (the month field). For single-part controls that did not have keyboard focus and are now receiving it, the entire control would receive keyboard focus when kControlFocusNextPart was passed in the param parameter. For single-part controls that already had keyboard focus and are now losing it, the entire control would lose keyboard focus. If you are passed kControlFocusNextPart and have run out of parts, return kControlFocusNoPart to indicate that the user tabbed past the control.
kControlFocusPrevPart
Your control definition function should change keyboard focus to its previous part, the entire control, or remove keyboard focus from the control, depending upon the circumstances. For multiple part controls that already had keyboard focus, the previous part of the control would receive keyboard focus when kControlFocusPrevPart was passed in the param parameter. For example, a clock control with keyboard focus would change its focus to the right-most element of the control (the year field). For single-part controls that did not have keyboard focus and are now receiving it, the entire control would receive keyboard focus when kControlFocusNextPart was passed in the param parameter. For single-part controls that already had keyboard focus and are now losing it, the entire control would lose keyboard focus. If you are passed kControlFocusPrevPart and have run out of parts, return kControlFocusNoPart to indicate that the user tabbed past the control.
<part code>
Your control definition function should focus on the specified part code. Your function can interpret this in any way it wishes.

Handling Keyboard Events

If your control definition function can handle keyboard events, it should return kControlSupportsFocus --every control that supports keyboard focus must also be able to handle keyboard events--as one of the feature bits in response to a kControlMsgGetFeatures message. If this bit is set, the Control Manager will pass kControlMsgKeyDown in the message parameter. The Control Manager passes a pointer to a control key down structure in the param parameter. Your control definition function should respond by processing the keyboard event as appropriate and return 0 as the function result.

The control key down structure is a structure of type ControlKeyDownRec :

struct ControlKeyDownRec {
    SInt16  modifiers;
    SInt16  keyCode;
    SInt16  charCode;
};
typedef struct ControlKeyDownRec ControlKeyDownRec;
typedef ControlKeyDownRec *ControlKeyDownPtr;
modifiers
The constant in the modifiers field of the event structure specifying the state of the modifier keys and the mouse button at the time the event was posted.
keyCode
The virtual key code derived from the event structure. This value represents the key pressed or released by the user. It is always the same for a specific physical key on a particular keyboard regardless of which modifier keys were also pressed.
charCode
A particular character derived from the event structure. This value depends on the virtual key code, the state of the modifier keys, and the current 'KCHR' resource.

Performing Idle Processing

If your control definition function can perform idle processing, it should return kControlWantsIdle as one of the feature bits in response to a kControlMsgGetFeatures message. If this bit is set and IdleControls is called for the window your control is in, the Control Manager will pass kControlMsgIdle in the message parameter. Your control definition function should ignore the param parameter and respond appropriately. For example, indeterminate progress indicators and asynchronous arrows use idle time to perform their animation.

Your control definition function should return 0 as the function result.


Getting and Setting Control-Specific Data

If your control definition function supports getting and setting control-specific data, it should return kControlSupportsDataAccess as one of its features bits in response to the kControlMsgGetFeatures message. If this bit is set, the Control Manager will call your control definition function and pass kControlMsgSetData in the message parameter when SetControlData is called, and will pass kControlMsgGetData in the message parameter when GetControlData and GetControlDataSize are called. The Control Manager passes a pointer to a control data access structure in the param parameter. Your definition function should respond by filling out the structure and returning an operating system status message as the function result.

The control data access structure is a structure of type ControlDataAccessRec:

struct ControlDataAccessRec{
    ResType     tag;
    ResType     part;
    Size        size;
    Ptr         dataPtr;
};
typedef struct ControlDataAccessRec ControlDataAccessRec;
typedef ControlDataAccessRec *ControlDataAccessPtr;

tag
A constant representing a piece of data that is passed in (in response to a kControlMsgSetData message) or returned (in response to a kControlMsgGetData message); see Control Data Tag Constants for a description of these constants. The control definition function should return errDataNotSupported if the value in the tag parameter is unknown or invalid.
part
The part of the control that this data should be applied to. If the information is not tied to a specific part of the control or the control has no parts, pass 0.
size
On entry, the size of the buffer pointed to by the dataPtr field. In response to a kControlMsgGetData message, this field should be adjusted to reflect the actual size of the data that the control is maintaining. If the size of the buffer being passed in is smaller than the actual size of the data, the control definition function should return errDataSizeMismatch .
dataPtr
A pointer to a buffer to read or write the information requested. In response to a kControlMsgGetData message, this field could be nil , indicating that you wish to return the size of the data in the size field.

Handling Activate and Deactivate Events

If your control definition function wants to be informed whenever it is being activated or deactivated, it should return kControlWantsActivate as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set and your control definition function is being activated or deactivated, the Control Manager calls it and passes kControlMsgActivate in the message parameter. The Control Manager passes a 0 or 1 in the param parameter. A value of 0 indicates that the control is being deactivated; 1 indicates that it is being activated.

Your control definition function should respond by performing any special processing before the user pane becomes activated or deactivated, such as deactivating its TEHandle or ListHandle if it is about to be deactivated.

Your control definition function should return 0 as the function result.


Setting a Control's Background Color or Pattern

If your control definition function supports embedding and draws its own background, it should return kControlHasSpecialBackground as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set and an embedding hierarchy of controls is being drawn in your control, the Control Manager passes kControlMsgSetUpBackground in the message parameter of your control definition function. The Control Manager passes a pointer to a filled-in control background structure in the param parameter. Your control definition function should respond by setting its background color or pattern to whatever is appropriate given the bit depth and device type passed in. Your control definition function should return 0 as the function result.

The control background structure is a structure of type ControlBackgroundRec :

struct ControlBackgroundRec {
    SInt16  depth;
    Boolean colorDevice;
};
typedef struct ControlBackgroundRec ControlBackgroundRec;
typedef ControlBackgroundRec *ControlBackgroundPtr;
depth
A signed 16-bit integer indicating the bit depth (in pixels) of the current graphics port.
colorDevice
A Boolean value. If true , you are drawing on a color device. If false , you are drawing on a monochrome device.

Supporting Live Feedback

If your control definition function supports live feedback while tracking the indicator, it should return kControlSupportsLiveFeedback as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set, the Control Manager will call your control definition function when it tracks the indicator and pass kControlMsgCalcValueFromPos in the message parameter. The Control Manager passes a handle to the indicator region being dragged in the param parameter.

Your control definition function should respond by calculating its value and drawing the control based on the new indicator region passed in. Your control definition function should not recalculate its indicator position. After the user is done dragging the indicator, your control definition function will be called with a posCntl message at which time you can recalculate the position of the indicator. Not recalculating the indicator position each time your control definition function is called creates a smooth dragging experience for the user.

Your control definition function should return 0 as the function result.


Being Informed When Subcontrols Are Added or Removed

If your control definition function wishes to be informed when subcontrols are added or removed, it should return kControlSupportsEmbedding as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set, the Control Manager passes ControlMsgSubControlAdded in the message parameter immediately after a subcontrol is added, or it passes kControlMsgSubControlRemoved just before a subcontrol is removed from your embedder control. A handle to the control being added or removed from the embedding hierarchy is passed in the param parameter. Your control definition function should respond appropriately and return 0 as the function result.

Typically, a control definition function only supports this message if it wants to do extra processing in response to changes in its embedded controls. Radio groups use these messages to perform necessary processing for handling embedded controls. For example, if a currently selected radio button is deleted, the group can adjust itself accordingly.


\xA9 1998 Apple Computer, Inc. – (Last Updated 19 Nov 98)