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 5 - Icon Utilities / Using the Icon Utilities


Drawing Icons in an Icon Family

You can define different versions of an icon for specific sizes and bit depths as part of a single icon family whose members share the same resource ID. If you define all your application's icons in icon families, you can use Icon Utilities routines to draw the icon using the icon family member that is best suited for the destination rectangle and the current bit depth of the display device. When your application uses Icon Utilities routines like PlotIconSuite or PlotIconID to plot icons, it doesn't have to determine which icon in the icon family is best suited for a given destination rectangle and bit depth; instead, the routines automatically display the appropriate icon.

You can also define individual icons of resource type 'ICON', 'cicn', or 'SICN' that are not part of an icon family and use Icon Utilities routines to draw them when necessary. For information about drawing these types of icons, see the section "Drawing Icons That Are Not Part of an Icon Family" beginning on page 5-13.

You can use the Icon Utilities to draw icons using modes or transforms that alter the icon's appearance in standard ways that are analogous to Finder states for icons. For example, the Finder draws a selected icon differently than it draws one that is not selected; to do so, the Finder specifies the transform constant ttSelected when it calls Icon Utilities routines to draw a selected icon. If you need to apply a particular transform to an icon, some Icon Utilities routines allow you to apply transforms for both standard Finder states and Finder label colors when you draw the icon.

Many of the Icon Utilities routines can also automatically align an icon within its destination rectangle. For example, the generic document icon that appears in the Finder is taller than it is wide. Some Icon Utilities routines allow you to draw such an icon without any special alignment, align it at the left or right of the destination rectangle, or use various other alignments.

Depending on the size of the rectangle, the Icon Utilities routines may stretch or shrink the icon to fit. To draw icons without stretching them, these routines require that the destination rectangle have the exact dimensions of a standard icon: that is, depending on the icon resource type, 32 by 32 pixels, 16 by 16 pixels, or 12 by 16 pixels. If you use destination rectangles of other sizes, these routines stretch or shrink the icons to fit the rectangles.

An icon family is a collection of icons representing a single object. Each icon in the family shares the same resource ID as other icons in the family but has its own resource type identifying the icon data it contains. The simplest way to draw an icon from an icon family is to pass the family's resource ID to the PlotIconID function, which draws the appropriate icon from the family for the specified destination rectangle and bit depth. The next section, "Drawing an Icon Directly From a Resource," describes how to use PlotIconID.

Alternatively, you can first use the GetIconSuite function to read the resource data for some or all icons in an icon family into memory. Given a resource ID and one or more resource types, the GetIconSuite function reads in resource data for each icon with the specified resource ID and resource types and collects handles to the resource data in an icon suite. An icon suite typically consists of one or more handles to icon resources from a single icon family that have been read into memory. The GetIconSuite function returns a handle for the requested icon suite; you can pass this handle to PlotIconSuite and other Icon Utilities routines. Like PlotIconID, PlotIconSuite draws the appropriate icon from an icon suite for the specified destination rectangle and bit depth. The section "Getting an Icon Suite and Drawing One of Its Icons" on page 5-11 describes how to use the GetIconSuite and PlotIconSuite routines.

An icon suite can in turn contain handles to each of the six icon resources that an icon family can contain, or it can contain handles to only a subset of the icon resources in an icon family. However, for best results, an icon suite should always include a black-and-white icon and icon mask for any icons you provide; that is, it should include a resource of type 'ICN#' in addition to any other large icons you provide as well as a resource of type 'ics#' in addition to any other small icons you provide. When you create an icon suite from icon family resources, the associated resource file should remain open while you use Icon Utilities routines.

Two types of handles exist in an icon suite: handles to icon data associated with a resource and handles to icon data that isn't associated with a resource. You typically use GetIconSuite to fill an icon suite with handles to icon resource data. You typically
use AddIconToSuite to add to an icon suite handles to icon data. When you use AddIconToSuite, the handles that you add to the suite do not have to be associated with a resource fork. For example, your application might get icon data from the desktop database rather than reading it from a resource, or your application might read icon data from a resource and then detach it. In either case, you can provide a handle to the icon data and use AddIconToSuite to add the handle to the icon suite.

An icon cache is like an icon suite, except that an icon cache also contains a pointer to an application-defined icon getter function and a pointer to data that is associated with the icon suite. You can pass a handle to an icon cache to any of the Icon Utilities routines that accept a handle to an icon suite. An icon cache typically does not contain handles to the icon resources for all icon family members. Instead, if the icon cache does not contain an entry for a specific type of icon in an icon family, the Icon Utilities routines call your application's icon getter function to retrieve the data for that icon type. The icon getter function should return either a handle to the icon data or NIL to indicate that no icon data exists for the specified icon type.

Drawing an Icon Directly From a Resource

To draw an icon from an icon family without first creating an icon suite, use the PlotIconID function. Listing 5-1 shows an application-defined procedure that draws an icon from an icon family. Given a resource ID, the PlotIconID function determines which member of the icon family to draw and then draws the icon in the given rectangle with the specified transform and alignment.

Listing 5-1 Drawing the icon from an icon family that is best suited to the user's display

PROCEDURE MyDrawIconFromFamily (resID: Integer; destRect: Rect);
VAR
   align:         IconAlignmentType;
   transform:     IconTransformType;
   myErr:         OSErr;
BEGIN
   align := atAbsoluteCenter; {specify alignment (centered)}
   transform := ttNone;       {specify no special transforms}
   {draw the icon, using the icon type best suited for the }
   { destination rect and current bit depth of the display device}
   myErr := PlotIconID(destRect, align, transform, resID);
END;
The PlotIconID function determines, from the size of the specified destination rectangle and the current bit depth of the display device, which icon of a given size from an icon family to draw. For example, if the coordinates of the destination rectangle are (100,100,116,116) and the display device is set to 4-bit color, the PlotIconID function draws the icon of type 'ics4' if that icon is available in the icon family.

If the width or height of a destination rectangle is greater than or equal to 32, PlotIconID uses the 32-by-32 pixel icon with the appropriate bit depth for the display device. If the destination rectangle is less than 32 by 32 pixels and greater than 16 pixels wide or 12 pixels high, PlotIconID uses the 16-by-16 pixel icon with the appropriate bit depth. If the destination rectangle's height is less than or equal to 12 pixels or its width is less than or equal to 16 pixels, PlotIconID uses the 12-by-16 pixel icon with the appropriate bit depth. (Typically only the Finder and the Standard File Package use 12-by-16 pixel icons.)

Depending on the size of the rectangle, the PlotIconID function may stretch or shrink the icon to fit. To draw icons without stretching them, PlotIconID requires that the destination rectangle have the exact dimensions of a standard icon: that is, depending on the icon resource type, 32 by 32 pixels, 16 by 16 pixels, or 12 by 16 pixels. If you use destination rectangles of other sizes, PlotIconID stretches or shrinks the icons to fit the rectangles.

Getting an Icon Suite and Drawing One of Its Icons

Listing 5-2 shows how you can use the GetIconSuite and PlotIconSuite functions to get an icon suite and then draw the icon from the suite that is best suited to the destination rectangle and the current bit depth of the display device.

Listing 5-2 Drawing the icon from an icon suite that is best suited to the display device

PROCEDURE MyDrawIconInSuite (resID: Integer; destRect: Rect; 
                             VAR iconSuiteHdl: Handle);
VAR
   iconType:      IconSelectorValue;
   align:         IconAlignmentType;
   transform:     IconTransformType;
   myErr:         OSErr;
BEGIN
   iconType := svAllAvailable;   {get all icons in icon family}
   myErr := GetIconSuite(iconSuiteHdl, resID, iconType);
   IF iconSuiteHdl <> NIL THEN
   BEGIN
      align := atAbsoluteCenter; {specify alignment (centered)}
      transform := ttNone;       {specify no special transforms}
      {draw the icon, using the icon type best suited for the }
      { destination rect & current bit depth of display device}
      myErr := PlotIconSuite(destRect, align, transform,
                             iconSuiteHdl);
   END;
END;
The application-defined procedure MyDrawIconInSuite shown in Listing 5-2 first uses the GetIconSuite function, specifying the constant svAllAvailable in the third parameter, to get all icons from the icon family with the specified resource ID and to collect the handles to the data for each icon into an icon suite. (You can use other constants in the third parameter of GetIconSuite to request only certain members of an icon family for an icon suite.) The MyDrawIconInSuite procedure then draws an icon from this suite using the PlotIconSuite function.

Like the PlotIconID function described in the previous section, the PlotIconSuite function determines, from the size of the specified destination rectangle and the current bit depth of the display device, which icon from the icon suite to draw.

You can also specify various transforms and alignments to PlotIconSuite. For example, the code in Listing 5-2 specifies that PlotIconSuite should center the icon within the destination rectangle.

Drawing Specific Icons From an Icon Family

In most cases you should use PlotIconID or PlotIconSuite to draw an icon from an icon family, because these routines automatically select the best version of an icon to display for a given destination rectangle and bit depth. The preceding sections, "Drawing an Icon Directly From a Resource" and "Getting an Icon Suite and Drawing One of Its Icons," describe how to use these routines.

If you need to plot a specific icon from an icon family rather than using the Icon Utilities to select a family member, you must first create an icon suite that contains only the icon from the desired resource type and its corresponding mask. You can then use PlotIconSuite to plot the icon. In this case PlotIconSuite still attempts to use the best icon available for the given destination rectangle and bit depth; however, by limiting the icon resources available in the icon suite, you can force PlotIconSuite to plot either the black-and-white icon from the 'ICN#' resource or just one of the other available resources. Listing 5-3 demonstrates how to do this.

Listing 5-3 Drawing a specific icon from an icon family or icon suite

PROCEDURE MyDrawThisIcon (destRect: Rect; resID: Integer;
                          VAR iconSuiteHdl: Handle);
VAR
   align:         IconAlignmentType;
   transform:     IconTransformType;
   myErr:         OSErr;
BEGIN
   {get only the 'ICN#' and 'icl4' icons and collect them in an }
   { icon suite}
   myErr := GetIconSuite(iconSuiteHdl, resID, 
                         svLarge1Bit + svLarge4Bit);
   IF iconSuiteHdl <> NIL THEN
   BEGIN
      align := atAbsoluteCenter; {specify alignment (centered)}
      transform := ttNone;       {specify no special transforms}
      {draw the best icon from the suite referenced by the icon }
      { suite handle; since the suite contains only 'ICN#' and }
      { 'icl4' icons, PlotIconSuite draws the best of the two}
      myErr := PlotIconSuite(destRect, align, transform,
                             iconSuiteHdl);
   END;
END;
The application-defined procedure MyDrawThisIcon passes the constants svLarge1Bit and svLarge4Bit to GetIconSuite. In response, GetIconSuite reads only the 'ICN#' and 'icl4' resources into memory, storing handles to the icon resource data in the icon suite. MyDrawThisIcon then uses PlotIconSuite to plot the best available icon from the suite.

If the bit depth of the display device is 1, the PlotIconSuite function in Listing 5-3 displays the black-and-white version of the icon from the 'ICN#' resource, regardless
of the size of the destination rectangle. If the bit depth of the display device is greater than 1, PlotIconSuite draws the icon from the 'icl4' resource, regardless of the size of the destination rectangle.

Manipulating Icons

You can use the GetIconFromSuite function to get a handle to the pixel data for a specific icon from an icon suite. You can use the handle returned by the function GetIconFromSuite to manipulate the icon data--for example, to alter its color or add three-dimensional shading--but not to draw the icon with other Icon Utilities routines such as PlotIconHandle.

Listing 5-4 provides an example of an application-defined procedure, MyGetIconData, that calls GetIconFromSuite and manipulates the icon data.

Listing 5-4 Manipulating icon data in memory

PROCEDURE MyGetIconData (iconType: ResType; iconSuite: Handle;
                         VAR iconHandle: Handle);
VAR 
   myErr: OSErr;
BEGIN
   {get the data for the icon with iconType from the suite}
   myErr := GetIconFromSuite(iconHandle, iconSuite, iconType);
   {do whatever with the data}
   myErr := MyManipulateIconData(iconHandle, iconType);
END;
The Icon Utilities also include routines that allow you to perform an action on one or more icons in an icon suite and to perform hit-testing on icons. For information about these routines, see "Performing Operations on Icons in an Icon Suite" and "Determining Whether a Point or Rectangle Is Within an Icon" beginning on page 5-38 and page 5-46, respectively.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
6 JUL 1996