Important: The information in this document is obsolete and should not be used for new development.
PATH![]() |
![]() ![]() |
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
defines a custom control. Changed with Appearance Manager 1.0.
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
theControl
message
message
parameter contains one of the task codes defined in Messages
. The subsections that follow explain each of these tasks in detail. param
message
parameter. If the task requires no data, this parameter is ignored.message
parameter.
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.
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;
drawCntl
testCntl
calcCRgns
initCntl
dispCntl
posCntl
thumbCntl
dragCntl
autoTrack
calcCntlRgn
calcThumbRgn
kControlMsgDrawGhost
kControlMsgCalcBestRect
kControlMsgHandleTracking
kControlMsgFocus
kControlMsgKeyDown
kControlMsgIdle
kControlMsgGetFeatures
kControlMsgSetData
kControlMsgGetData
kControlMsgActivate
kControlMsgSetUpBackground
kControlMsgSubValueChanged
kControlMsgCalcValueFromPos
kControlMsgTestNewMsgSupport
kControlMsgSubControlAdded
kControlMsgSubControlRemoved
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
};
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.
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.
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. ThecalcCntlRgn
andcalcThumbRgn
messages will be sent instead.
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.
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.
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.
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.
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
slopRect
limitRect
parameter.axis
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
.
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
};
Note
When the Appearance Manager is present, the message
kControlMsgHandleTracking
should be sent instead ofdragCntl
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
.
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 theparam
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 .
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 '
};
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
};
kControlSupportsGhosting
If this bit (bit 0) is set, the control definition function supports the kControlMsgDrawGhost
message. kControlSupportsEmbedding
kControlMsgSubControlAdded
and kControlMsgSubControlRemoved
messages.kControlSupportsFocus
kControlMsgKeyDown
message. If this bit and the kControlGetsFocusOnClick
bit are set, the control definition function supports the kControlMsgFocus
message.kControlWantsIdle
kControlMsgIdle
message.kControlWantsActivate
kControlMsgActivate
message.kControlHandlesTracking
kControlMsgHandleTracking
message. kControlSupportsDataAccess
kControlMsgGetData
and kControlMsgSetData
messages.kControlHasSpecialBackground
kControlMsgSetUpBackground
message. kControlGetsFocusOnClick
If this bit (bit 8) and the kControlSupportsFocus
bit are set, the control definition function supports the kControlMsgFocus
message.kControlSupportsCalcBestRect
kControlMsgCalcBestRect
message. kControlSupportsLiveFeedback
kControlMsgCalcValueFromPos
message. kControlHasRadioBehavior
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.
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;
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
where
field of the event structure.modifiers
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
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
).
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;
kControlFocusNoPart
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
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
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>
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
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
charCode
'KCHR'
resource.
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.
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.
ControlDataAccessRec:
struct ControlDataAccessRec{
ResType tag;
ResType part;
Size size;
Ptr dataPtr;
};
typedef struct ControlDataAccessRec ControlDataAccessRec;
typedef ControlDataAccessRec *ControlDataAccessPtr;
tag
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
size
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
kControlMsgGetData
message, this field could be nil
, indicating that you wish to return the size of the data in the size
field.
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.
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;
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.
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.