Important: The information in this document is obsolete and should not be used for new development.
Providing Help Balloons for Dynamic Windows
To create help balloons for objects whose location in the content area of windows may vary, your application needs to use Help Manager routines to display and remove balloons as the user moves the cursor.
You should display or remove help balloons for dynamic windows at the same time that you normally check the mouse location to display or change the cursor. For example,
- Note
- Nonprogrammers can use the BalloonWriter tool to provide you with delimited ASCII text that you can then use in conjunction with Help Manager routines to display balloons for dynamic windows. However, BalloonWriter does not create the resources or routines necessary to automatically display help balloons for these types of windows.
if you provide your ownDoIdle
procedure (as described in the chapter "Event Manager" in Inside Macintosh: Macintosh Toolbox Essentials), you can also check the mouse location and, if the cursor is located in a hot rectangle, you should display the associated help balloon.To create help balloons for the content area of a dynamic window, you need to
After defining all the hot rectangles within your content region, create separate
- identify the hot rectangles for each area or object
- create data structures to store the locations of the hot rectangles
- determine how to calculate their changing locations
- track and update the hot rectangles
- use the
HMShowBalloon
function to display a help balloon when the cursor is located in a hot rectangle
'STR '
,'STR#'
,'PICT'
, or'TEXT'
and'styl'
resources for the help balloons' messages. You don't have to store the help messages in these resources when usingHMShowBalloon
, but doing so makes your application easier to localize.When you use the
HMShowBalloon
function, your application is responsible for tracking the cursor and determining when to display the help balloon. If you use theHMShowBalloon
function, you can let the Help Manager track the cursor and determine when to remove the help balloon, or your application can remove the balloon when necessary by calling theHMRemoveBalloon
function. If you display your own help balloons using theHMShowBalloon
function, you should use theHMGetBalloons
function to determine whether help is enabled before displaying a help balloon. If help is not enabled, you don't need to call any Help Manager routines that display balloons, because they won't do anything unlessHMGetBalloons
returnsTRUE
.The
HMShowBalloon
function is useful for
For example, windows with scrolling icons (such as the Users & Groups dynamic window shown in Figure 3-18 on page 3-59) require you to use
- windows whose content changes
- windows that can be resized
- windows that contain hot rectangles with variable locations
- situations in which you want your application to have more control over the display and removal of the help balloon
HMShowBalloon
to display help balloons for the icons. Likewise, if you have tools--such as rulers that users configure for tab stops in a word-processing document--that scroll with a document, you'll need to useHMShowBalloon
to display help balloons for the scrolling tools.When using
HMShowBalloon
, you specify the help message, the balloon tip's coordinates, an alternate rectangle to use if the Help Manager needs to move the tip, an optional pointer to a function that can modify the tip and alternate rectangle coordinates, the balloon definition function, and the variation code. In the final parameter to theHMShowBalloon
function, provide a constant that tells the Help Manager whether to save the bits behind the balloon.
myErr := HMShowBalloon(aHelpMsg, tip, alternateRect, tipProc, theProc, variant, method);Specify the help message in a help message record, which you pass in theaHelpMsg
parameter to theHMShowBalloon
function. You can specify the help message for each hot rectangle using text strings,'STR '
resources,'STR#'
resources, styled text resources,'PICT'
resources, handles to styled text records, or handles to pictures.The
HMMessageRecord
data type defines the help message record.
TYPE HMMessageRecord = RECORD hmmHelpType: Integer; {type of next field} CASE Integer OF khmmString: (hmmString: Str255); {Pascal string} khmmPict: (hmmPict: Integer); {'PICT' resource ID} khmmStringRes: (hmmStringRes: HMStringResType); {'STR#' resource } { ID and index} khmmTEHandle: (hmmTEHandle: TEHandle); {TextEdit handle} khmmPictHandle: (hmmPictHandle: PicHandle); {picture handle} khmmTERes: (hmmTERes: Integer); {'TEXT'/'styl' } { resource ID} khmmSTRRes: (hmmSTRRes: Integer);{'STR ' resource ID} END;ThehmmHelpType
field specifies the data type of the second field of the help message record. You specify one of these constants for thehmmHelpType
field.
CONST khmmString = 1; {Pascal string} khmmPict = 2; {'PICT' resource ID} khmmStringRes = 3; {'STR#' resource ID and index} khmmTEHandle = 4; {TextEdit handle} khmmPictHandle = 5; {picture handle} khmmTERes = 6; {'TEXT' and 'styl' resource ID} khmmSTRRes = 7; {'STR ' resource ID}You specify the help message itself in the second field of the help message record.You can specify the help message by using a text string, a text string stored in a resource of type
'STR '
, or a text string stored as an'STR#'
resource. You can also provide the information using styled text resources, or you can provide a handle to a styled text record. If you want to provide a picture for the help message, you can use a resource of type'PICT'
or provide a handle to a picture.Listing 3-11 illustrates how to specify a Pascal string using the
khmmString
constant in the help message record. (Although you can specify a string from within your code, storing the strings in resources and then accessing them through the Resource Manager makes localization easier.)Listing 3-11 Using a string resource as the help message for
HMShowBalloon
PROCEDURE DoTextStringBalloon; VAR aHelpMsg: HMMessageRecord; tip: Point; alternateRect: RectPtr; err: OSErr; BEGIN aHelpMsg.hmmHelpType := khmmString; aHelpMsg.hmmString := 'To turn the page, click here.'; MySetTipAndAltRect(tip, alternateRect); {initialize values} err := HMShowBalloon(aHelpMsg, tip, alternateRect, NIL, 0, 0, kHMRegularWindow); END;To use a picture, you can either store the picture as a'PICT'
resource or create the'PICT'
graphic from within your application and provide a handle to it. Because the Help Manager uses the resource itself or the actual handle that you pass toHMShowBalloon
, your'PICT'
resource should be purgeable, or, when using a handle to a'PICT'
resource, you should release the handle or dispose of it when you are finished with it.Listing 3-12 illustrates how to use the
khmmPict
constant for specifying a'PICT'
resource ID in a help message record. The help message record is then passed in theaHelpMsg
parameter of theHMShowBalloon
function.Listing 3-12 Using a picture resource as the help message for
HMShowBalloon
PROCEDURE DoPictBalloon; VAR aHelpMsg: HMMessageRecord; tip: Point; alternateRect: RectPtr; err: OSErr; BEGIN aHelpMsg.hmmHelpType := khmmPict; aHelpMsg.hmmPict := 128; {resource ID of 'PICT' resource} MySetTipAndAltRect(tip, alternateRect); {initialize values} err := HMShowBalloon(aHelpMsg, tip, alternateRect, NIL, 0, 0, kHMRegularWindow); END;Listing 3-13 illustrates how to specify a handle to a'PICT'
resource using thekhmmPictHandle
constant in the help message record. The help message record is then passed to theHMShowBalloon
function in theaHelpMsg
parameter.Listing 3-13 Using a handle to a picture resource as the help message for
HMShowBalloon
PROCEDURE DoPictBalloon2; VAR pict: PicHandle; aHelpMsg: HMMessageRecord; tip: Point; pictFrame: Rect; alternateRect: RectPtr; err: OSErr; BEGIN MySetPictFrame(pictFrame); {initialize pictFrame} pict := OpenPicture(pictFrame); DrawString('Test Balloon'); ClosePicture; aHelpMsg.hmmHelpType := khmmPictHandle; aHelpMsg.hmmPictHandle := pict; MySetTipAndAltRect(tip, alternateRect); {initialize values} err := HMShowBalloon(aHelpMsg, tip, alternateRect, NIL, 0, 0, kHMRegularWindow); KillPicture(pict); END;To specify a help message stored in a string list ('STR#'
resource) in a help message record, you must first create a Help Manager string list record. TheHMStringResType
data type defines a Help Manager string list record.
TYPE HMStringResType = RECORD hmmResID: Integer; {resource ID of 'STR#' resource} hmmIndex: Integer; {index of string} END;ThehmmResID
field specifies the resource ID of the'STR#'
resource, and thehmmIndex
field specifies the index of a string within that resource.To use a string stored in an
'STR#'
resource with theHMShowBalloon
function, use thekhmmStringRes
constant in thehmmHelpType
field of the help message record, and supply thehmmStringRes
field with a Help Manager string list record, as shown in Listing 3-14.Listing 3-14 Using a string list resource as the help message for
HMShowBalloon
PROCEDURE DoStringListBalloon; VAR aHelpMsg: HMMessageRecord; tip: Point; alternateRect: RectPtr; khmmStringRes: HMStringResType; err: OSErr; BEGIN aHelpMsg.hmmHelpType := khmmStringRes; aHelpMsg.hmmStringRes.hmmResID := 1000; aHelpMsg.hmmStringRes.hmmIndex := 1; MySetTipAndAltRect(tip, alternateRect); {initialize values} err := HMShowBalloon(aHelpMsg, tip, alternateRect, NIL, 0, 0, kHMRegularWindow); END;To use styled text resources with theHMShowBalloon
function, use thekhmmTERes
constant in thehmmHelpType
field of the help message record. In the next field, supply a resource ID that is common to both a'TEXT'
resource and a style scrap ('styl'
) resource. For example, you might create a'TEXT'
resource that contains the words "Displays your text in boldface print." You would also create a'styl'
resource (with the same resource ID as the'TEXT'
resource) that applies boldface style to the word "boldface." When you specify theHMTEResItem
constant and the resource ID number of the'TEXT'
and'styl'
resources, the Help Manager employs TextEdit routines to display your text with your prescribed styles.To use a handle to a styled text record, supply the
khmmTEHandle
constant in thehmmHelpType
field, as illustrated in Listing 3-15.Listing 3-15 Using styled text resources as the help message for
HMShowBalloon
PROCEDURE DoStyledTextBalloon; VAR aHelpMsg: HMMessageRecord; tip: Point; alternateRect: RectPtr; hTE: TEHandle; err: OSErr; BEGIN hTE := TEStyleNew(destRect, viewRect); {or, use TENew} {be sure to fill in data in handle here} aHelpMsg.hmmHelpType := khmmTEHandle; aHelpMsg.hmmTEHandle := hTE; MySetTipAndAltRect(tip, alternateRect); {initialize values} err := HMShowBalloon(aHelpMsg, tip, alternateRect, NIL, 0, 0, kHMRegularWindow); END;When using theHMShowBalloon
function, you specify the tip in thetip
parameter and the rectangle pointed to in thealternateRect
parameter in global coordinates. The Help Manager calculates the location and size of the help balloon. If the help balloon fits onscreen, the Help Manager displays the help balloon using the specified tip.If you use the previously described help resources to define help balloons, the Help Manager uses the hot rectangles you specify in the help resources for two purposes: first, to associate areas of the screen with help balloons and, second, to move the tip if the help balloon doesn't fit onscreen.
However, if you use the
HMShowBalloon
function to display help balloons, you must identify hot rectangles, create your own data structures to store their locations, track the cursor yourself, and callHMShowBalloon
when the cursor moves to your hot rectangles. The Help Manager does not know the locations of your hot rectangles, so it cannot use them for moving the tip if the help balloon is placed offscreen. Instead, the Help Manager uses the alternate rectangle that you point to with thealternateRect
parameter. Often, you specify the same coordinates for the alternate rectangle that you specify for your hot rectangle. However, you may choose to make your alternate rectangle smaller or larger than your hot rectangle. If you make your alternate rectangle smaller than your hot rectangle, you have greater assurance that the Help Manager will be able to fit the help balloon onscreen; if you specify an alternate rectangle that is larger than your hot rectangle, you have greater assurance that the help balloon will not obscure some object explained by the balloon.By specifying a rectangle in the
alternateRect
parameter, you tell the Help Manager to callHMRemoveBalloon
to automatically remove the balloon when the cursor leaves the area bounded by the rectangle. However, if you specifyNIL
for thealternateRect
parameter, your application is responsible for tracking the cursor and determining when to remove the help balloon. When you specifyNIL
, the Help Manager also does not attempt to calculate a new tip position if the help balloon is offscreen.Use the
tipProc
parameter (the fourth parameter toHMShowBalloon
) to specify the tip function called by the Help Manager before displaying the balloon. SpecifyNIL
to use the Help Manager's default tip function, or supply your own tip function and point to it in this parameter. Writing your own tip function is described in "Application-Defined Routines" beginning on page 3-120.
Use the parameter
- Note
- When you call the
HMShowBalloon
function, the Help Manager does not display the help balloon or attempt to move the tip under either of these conditions:- The help balloon's tip is offscreen or in the menu bar, and you don't specify an alternate rectangle.
- Both the help balloon's tip and the alternate rectangle are offscreen.
theProc
(the fifth parameter) to specify a balloon definition function. To use the standard balloon definition function, specify 0 in this parameter. To use your own balloon definition function, specify the resource ID of the'WDEF'
resource containing your balloon definition function. Writing your own balloon definition function is described in "Writing Your Own Balloon Definition Function" on page 3-86.Supply a variation code for the balloon definition function in the
variant
parameter (the sixth parameter toHMShowBalloon
). Specify 0 in thevariant
parameter to use the default help balloon shape, specify a code from 1 to 7 to use one of the other positions provided by the standard balloon definition function, or specify a code to use one of the positions provided by your own balloon definition function.Use the
method
parameter (the last parameter toHMShowBalloon
) to specify how the Help Manager should draw and remove the balloon. Use the following constants for the parameter.
CONST kHMRegularWindow = 0; {don't save bits; just update} kHMSaveBitsNoWindow = 1; {save bits; don't do update} kHMSaveBitsWindow = 2; {save bits; do update event}If you specifykHMRegularWindow
, the Help Manager draws and removes the help balloon as if it were a window. That is, when drawing the balloon, the Help Manager does not save bits behind the balloon, and when removing the balloon, the Help Manager generates an update event. This is the standard behavior of help balloons; it is the behavior you should normally use.If you specify
kHMSaveBitsNoWindow
in themethod
parameter, the Help Manager does not create a window for displaying the balloon. Instead, the Help Manager creates a help balloon that is more like a menu than a window. The Help Manager saves the bits behind the balloon when it creates the balloon. When it removes the balloon, the Help Manager restores the bits without generating an update event. You should use this technique only in a modal environment where the bits behind the balloon cannot change from the time the balloon is drawn to the time it is removed. For example, you might specify thekHMSaveBitsNoWindow
constant when providing help balloons for pop-up menus that overlay complex graphics, which might take a long time to redraw with an update event.If you specify
kHMSaveBitsWindow
, the Help Manager treats the help balloon as a hybrid having properties of both a menu and a window. That is, the Help Manager saves the bits behind the balloon when it creates the balloon, and when it removes the balloon, it both restores the bits and generates an update event. You'll rarely need this option. It is necessary only in a modal environment that might immediately change to a nonmodal environment--that is, where the bits behind the help balloon are static when the balloon is drawn, but can possibly change before the help balloon is removed.Listing 3-16 shows a sample routine that displays help balloons for hot rectangles within the content area of a window.
Listing 3-16 Using
HMShowBalloon
to display help balloons
PROCEDURE FindAndShowBalloon (window: WindowPtr); VAR i: Integer; mouse: Point; savePort: GrafPtr; helpMsg: HMMessageRecord; inRect: Boolean; hotRect: Rect; result: OSErr; BEGIN IF (window = FrontWindow) THEN {only do frontmost windows} BEGIN GetPort(savePort); {save the old port for later} SetPort(window); {set the port to the front window} GetMouse(mouse); {get the mouse location in local } { coords} inRect := FALSE; {clear flag saying mouse location } { wasn't in any hot rectangle} IF PtInRect(mouse, window^.portRect) THEN {if the cursor is in the window} FOR i := 1 TO 10 DO {check all ten predefined hot } { rectangles in the window} IF PtInRect(mouse, MyPredefinedRects[i]) THEN BEGIN {the cursor is in a hot rectangle} IF (i <> gLastBalloon) THEN {user moved cursor to a different hot rectangle} BEGIN hotRect := MyPredefinedRects[i]; LocalToGlobal(hotRect.topLeft); {converting rect to global} LocalToGlobal(hotRect.botRight); WITH hotRect DO {put the tip in the middle} SetPt(mouse, (right + left) div 2, (bottom + top) div 2); helpMsg.hmmHelpType := khmmStringRes; {get help message from an 'STR#' resource} helpMsg.hmmStringRes.hmmResID := kHelpMsgsID; helpMsg.hmmStringRes.hmmIndex := i; result := HMShowBalloon (helpMsg, {use just-made help msg} mouse, {pointing to this tip} @MyPredefinedRects[i], {use hot } { rect for alt rect} NIL, {no special tip proc} 0,0, {using default balloon} kHMRegularWindow);{don't save bits behind} IF (result = noErr) THEN {then remember balloon} gLastBalloon := i; END; inRect := TRUE; {remember when the } { cursor is in any hot rect} END; IF not inRect THEN gLastBalloon := -1; {clear last balloon global for } { no hit} SetPort(savePort); {restore the port} END; END; {FindAndShowBalloon}TheFindAndShowBalloon
procedure in Listing 3-16 tracks the cursor, and, if the cursor is located in a predefined hot rectangle, it displays a help balloon for that rectangle. In this example there are ten predefined rectangles (in theMyPredefinedRects
array) and ten corresponding help messages in an'STR#'
resource (of IDkHelpMsgsID
)--one message for each hot rectangle. Other supporting routines can update the coordinates of the hot rectangles as their locations change.You can also use the
HMShowBalloon
function from the event filter function of a modal dialog box or an alert box. See the chapter "Dialog Manager" in Inside Macintosh: Macintosh Toolbox Essentials for information on event filter functions.