Legacy Documentclose button

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

Previous Book Contents Book Index Next

Inside Macintosh: More Macintosh Toolbox /
Chapter 6 - Component Manager / Creating Components


The Structure of a Component

Every component must have a single entry point that returns a value of type ComponentResult (a long integer). Whenever the Component Manager receives a request for your component, it calls your component's entry point and passes
any parameters, along with information about the current connection, in a component parameters record. The Component Manager also passes a handle to the global storage (if any) associated with that instance of your component.

When your component receives a request, it should examine the parameters to determine the nature of the request, perform the appropriate processing, set an error code if necessary, and return an appropriate function result to the Component Manager.

The component parameters record is defined by a data structure of type ComponentParameters.

TYPE ComponentParameters = 
      PACKED RECORD
         flags:      Char;                   {reserved}
         paramSize:  Char;                   {size of parameters}
         what:       Integer;                {request code}
         params:     ARRAY[0..0] OF LongInt; {actual parameters}
      END;
The what field contains a value that specifies the type of request. Negative values are reserved for definition by Apple. You can use values greater than or equal to 0 to define other requests that are supported by your component. Follow these guidelines when defining your request codes: request codes between 0 and 256 are reserved for definition by components of a given type and a given type-subtype. Use request codes greater than 256 for requests that are unique to your component. For example, a certain component of a certain type-subtype might support values 0 through 5 as requests that are supported by all components of that type, values 128 through 140 as requests that are supported by all components of that given type-subtype, and values 257 through 260 as requests supported only by that component.

Table 6-1 shows the request codes defined by Apple and the actions your component should take upon receiving them. Note that four of the request codes--open, close, can do, and version--are required. Your component must respond to these four request codes. These request codes are described in greater detail in "Handling Requests for Service" beginning on page 6-18.
Table 6-1 Request codes (Continued)
Request codeAction your component should performRequired
kComponentOpenSelectOpen a connectionYes
kComponentCloseSelectClose an open connectionYes
kComponentCanDoSelectDetermine whether your component supports a particular requestYes
kComponentVersionSelectReturn your component's version numberYes
kComponentRegisterSelectDetermine whether your component can operate in the current environmentNo
kComponentTargetSelectCall another component whenever it would call itself (as a result of your component being used by another component)No
kComponentUnregisterSelectPerform any operations that are necessary as a result of your component being unregisteredNo

The example drawing component (shown in Listing 6-5 on page 6-16) supports the four required request codes, and in addition supports the request codes that are required for all components of the type 'draw'. All drawing components must support these request codes:

CONST
      kDrawerSetUpSelect      = 0;  {set up drawing region}
      kDrawerDrawSelect       = 1;  {draw the object}
      kDrawerEraseSelect      = 2;  {erase the object}
      kDrawerClickSelect      = 3;  {determine if cursor is }
                                    { inside of the object}
      kDrawerMoveSelect       = 4;  {move the object}
The params field of the component parameters record is an array that contains the parameters specified by the application that called your component. You can directly extract the parameters from this array, or you can use the CallComponentFunction or CallComponentFunctionWithStorage function to extract the parameters from this array and pass these parameters to a subroutine of your component (see page 6-61 and page 6-62 for more information about these functions).

Listing 6-5 shows the structure of a drawing component--a simple component that draws an object on the screen. The component subtype of a drawing component indicates the type of object the component draws. This particular drawing component is of the subtype 'oval'; it draws oval objects.

Whenever an application calls your component, the Component Manager calls your component's main entry point (for example, the OvalDrawer function). This entry point must be the first function in the component's code segment.

As previously described, the Component Manager passes two parameters to your component: a component parameters record and a parameter of type Handle.
The parameters specified by the calling application are contained in the component parameters record. Your component can access the parameters directly from this record. Alternatively, as shown in Listing 6-5, you can use Component Manager routines to extract the parameters from this array and invoke a subroutine of your component. By taking advantage of these routines, you can simplify the structure of your component code.

The OvalDrawer function first examines the value of the what field of the component parameters record. The what field contains the request code. The OvalDrawer function performs the action specified by the request code. The OvalDrawer function uses a number of subroutines to carry out the desired action. It uses the Component Manager routines CallComponentFunction and CallComponentFunctionWithStorage to extract the parameters from the component parameters record and to call the specified component's subroutine with these parameters.

For example, when the drawing component receives the request code kComponentOpenSelect, it calls the function CallComponentFunction. It passes the component parameters record and a pointer to the component's OvalOpen subroutine as parameters to CallComponentFunction. This function extracts the parameters and calls the OvalOpen function. The OvalOpen function allocates memory for this instance of the component. Your component can allocate memory to hold global data when it receives an open request. To do this, allocate the memory and then call the SetComponentInstanceStorage function. This function associates the allocated memory with the current instance of your component. The next time this instance of your component is called, the Component Manager passes a handle to your previously allocated memory in the storage parameter. For additional information on handling the open request, see "Responding to the Open Request" on page 6-18.

When the drawing component receives the drawing setup request (indicated by the kDrawerSetupSelect constant), it calls the Component Manager function CallComponentFunctionWithStorage. Like CallComponentFunction, this function extracts the parameters and calls the specified subroutine (OvalSetup) . The CallComponentFunctionWithStorage function also passes as a parameter to the subroutine a handle to the memory associated with this instance of the component. The OvalSetup subroutine can use this memory as needed. For additional information on handling the drawing setup request, see "Responding to Component-Specific Requests" on page 6-25.

Listing 6-5 A drawing component for ovals

UNIT Ovals;
INTERFACE
{include a USES statement if required}

FUNCTION OvalDrawer (params: ComponentParameters; 
                     storage: Handle): ComponentResult;

IMPLEMENTATION

CONST
   kOvalDrawerVersion      = 0;  {version number of this component}

   kDrawerSetUpSelect      = 0;  {set up drawing region}
   kDrawerDrawSelect       = 1;  {draw the object}
   kDrawerEraseSelect      = 2;  {erase the object}
   kDrawerClickSelect      = 3;  {determine if cursor is }
                                 { inside of the object}
   kDrawerMoveSelect       = 4;  {move the object}
TYPE
   GlobalsRecord =
      RECORD
         bounds:              Rect;
         boundsRgn:           RgnHandle;
         self:                ComponentInstance;
      END;
   GlobalsPtr     = ^GlobalsRecord;
   GlobalsHandle  = ^GlobalsPtr;

{any subroutines used by the component go here}

FUNCTION OvalDrawer (params: ComponentParameters; 
                     storage: Handle): ComponentResult;
BEGIN
   {perform action corresponding to request code}
   IF params.what < 0 THEN    {handle the required request codes}
      CASE (params.what) OF   
      kComponentOpenSelect: 
         OvalDrawer := CallComponentFunction(params,
                                             ComponentRoutine(@OvalOpen));
      kComponentCloseSelect: 
         OvalDrawer := CallComponentFunctionWithStorage(storage, params,
                                              ComponentRoutine(@OvalClose));
      kComponentCanDoSelect: 
         OvalDrawer := CallComponentFunction(params,
                                             ComponentRoutine(@OvalCanDo));
      kComponentVersionSelect: 
         OvalDrawer := kOvalDrawerVersion;
      OTHERWISE 
         OvalDrawer := badComponentSelector;
      END {of CASE}
   ELSE                    {handle component-specific request codes}
      CASE (params.what) OF
      kDrawerSetupSelect: 
         OvalDrawer := CallComponentFunctionWithStorage
                                             (storage, params, 
                                              ComponentRoutine(@OvalSetup));
      kDrawerDrawSelect: 
         OvalDrawer := CallComponentFunctionWithStorage
                                             (storage, params, 
                                              ComponentRoutine(@OvalDraw));
      kDrawerEraseSelect: 
         OvalDrawer := CallComponentFunctionWithStorage
                                             (storage, params, 
                                              ComponentRoutine(@OvalErase));
      kDrawerClickSelect: 
         OvalDrawer := CallComponentFunctionWithStorage
                                             (storage, params, 
                                              ComponentRoutine(@OvalClick));
      kDrawerMoveSelect: 
         OvalDrawer := CallComponentFunctionWithStorage
                                             (storage, params, 
                                              ComponentRoutine(@OvalMoveTo));
     OTHERWISE 
         OvalDrawer := badComponentSelector;
   END;  {of CASE}
END; {of OvalDrawer}

END.
The next section describes how your component should respond to the required request codes. Following sections provide more information on


Previous Book Contents Book Index Next

© Apple Computer, Inc.
6 JUL 1996