Important: The information in this document is obsolete and should not be used for new development.
Using an Application-Defined Item to Draw the Bold Outline
You can define your own type of item for dialog boxes. You might wish, for example,
for a Default Button
to display a clock with the current time in a dialog box. You can also use application- defined items to draw a bold outline around the default button in a dialog box.You should not use application-defined items in an alert box because they add unnecessary programming complications. If you need an application-defined item,
use a dialog box instead.To define your own item, include an item of type
UserItem
in your item list resource;
it should have a display rectangle, but no text and no resource ID associated with
it. The dialog resource that uses this item list resource must specify theinvisible
constant. This makes the dialog box invisible while you install a draw procedure for your application-defined item. After installing the procedure that draws the application- defined item, you display the dialog box by using the Window Manager procedureShowWindow
.For example, Figure 6-32 on page 6-48 illustrates a dialog box that outlines the default button (Spell Check). To outline the button, the application must add an item of type
UserItem
to the item list resource for that dialog box.So that an application-defined drawing procedure can draw a border around the Spell Check button, the item list resource in Listing 6-15 specifies a larger display rectangle for the application-defined item than for the Spell Check button.
Listing 6-15 Rez input for an application-defined item in an item list
resource 'DITL' (kSpellCheckDITL, purgeable) { /*ITEM NO. 1: OK button--the default*/ { {123, 170, 144, 254}, Button {enabled,"Spell Check"}, /*ITEMs 2-5 go here: Cancel button, two checkboxes, and static text*/ /*ITEM NO. 6: application-defined item*/ {115, 164, 152, 260}, /*6th item*/ UserItem { /*draw procedure for item draws an outline*/ disabled, /*1st item lies inside this--1st is enabled*/ } } };The application-defined item is disabled because the Spell Check button, which lies within the application-defined item, is enabled. Because the Spell Check button is listed before the application-defined item in this item list resource, the Dialog Manager reports when the user clicks the Spell Check button. However, note that when application- defined items are enabled, the Dialog Manager reports their item numbers when the
user clicks them.
Listing 6-14 on page 6-49 shows the dialog resource for the dialog box. Notice that the
- Note
- Although the draw procedure for an application-defined item can draw outside the item's display rectangle, this is not recommended because
if the Dialog Manager receives an update event involving an area outside the display rectangle but inside the area where you draw
your application-defined item, the Dialog Manager won't call your
draw procedure.invisible
constant in the dialog resource specifies that the dialog box should initially be invisible.You must provide a procedure that draws your application-defined item. Your draw procedure must have two parameters: a dialog pointer and an item number from the dialog box's item list resource. For example, this is how you should declare the draw procedure if you were to name it
MyDrawDefaultButtonOutline
:
PROCEDURE MyDrawDefaultButtonOutline (theDialog: DialogPtr; theItem: Integer);The parametertheDialog
is a pointer to the dialog box containing the application- defined item. (If your procedure draws in more than one dialog box, this parameter tells
your procedure which dialog box to draw in.) The parametertheItem
is a number corresponding to the position of an item in the item list resource for the dialog box. (In case the procedure draws more than one item, this parameter tells the procedure which one to draw.)To install this draw procedure, use the
GetDialogItem
andSetDialogItem
procedures. UseGetDialogItem
to return a handle to the application-defined item specified in the item list resource. Then useSetDialogItem
to replace this handle
with a pointer to your draw procedure. When calling your draw procedure, the Dialog Manager sets the current port to the dialog box's graphics port. The Dialog Manager then calls your procedure to draw the application-defined item as necessary--for instance, when you display the dialog box and whenever the Dialog Manager receives an update event for the dialog box.Listing 6-16 illustrates how to install the procedure that draws a bold outline. In this listing,
GetDialogItem
gets a handle to the application-defined item (which is
the sixth item in the item list resource from Listing 6-15). The procedure pointer@MyDrawDefaultButtonOutline
, which is coerced to a handle, is then passed
toSetDialogItem
, which sets the draw procedure into the dialog record.Listing 6-16 Installing the draw procedure for an application-defined item
FUNCTION DisplayMyDialog (VAR theDialog: DialogPtr): OSErr; VAR itemType: Integer; itemHandle: Handle; itemRect: Rect; docWindow: WindowPtr; event: EventRecord; BEGIN {begin by creating an invisible dialog box} theDialog := GetNewDialog(kSpellCheckID, NIL, Pointer(-1)); IF theDialog <> NIL THEN BEGIN {get a handle to the application-defined item (i.e., userItem)} GetDialogItem(theDialog, kUserItem, itemType, itemHandle, itemRect); {install the drawing procedure for the application-defined item} SetDialogItem(theDialog, kUserItem, itemType, Handle(@MyDrawDefaultButtonOutline), itemRect); docWindow := FrontWindow; {get the front window} {if there's a front window, deactivate it} IF docWindow <> NIL THEN DoActivate(docWindow, FALSE, event); ShowWindow(theDialog); {display the dialog box} MyAdjustMenus; {adjust menus as needed} DisplayMyDialog := kSuccess; END ELSE DisplayMyDialog := kFailed; {call ModalDialog and handle events in dialog box here} END;Use the Window Manager procedureShowWindow
to display the previously invisible dialog box. WhenShowWindow
is called in this example, a bold outline is drawn inside the application-defined item and around the Spell Check button.Listing 6-17 shows a procedure that draws a bold outline around a button of any size and shape. This procedure can be used to draw the outline around the Spell Check button from the previous example.
Listing 6-17 Creating a draw procedure that draws a bold outline around the default button
PROCEDURE MyDrawDefaultButtonOutline(theDialog: DialogPtr; theItem: Integer); CONST kButtonFrameInset = -4; kButtonFrameSize = 3; kCntrActivate = 0; VAR itemType: Integer; {returned item type} itemRect: Rect; {returned display rectangle} itemHandle: Handle; {returned item handle} curPen: PenState; buttonOval: Integer; fgSaveColor: RGBColor; bgColor: RGBColor; newfgColor: RGBColor; newGray: Boolean; oldPort: WindowPtr; isColor: Boolean; targetDevice: GDHandle; BEGIN {get the default button & draw a bold border around it} GetDialogItem(theDialog, kDefaultButton, itemType, itemHandle, itemRect); GetPort(oldPort); SetPort(ControlHandle(itemHandle)^^.contrlOwner); GetPenState(curPen); PenNormal; InsetRect(itemRect, kButtonFrameInset, kButtonFrameInset); FrameRoundRect(itemRect, 16, 16); buttonOval := (itemRect.bottom - itemRect.top) DIV 2 + 2; IF ((CGrafPtr(ControlHandle(itemHandle)^^.contrlOwner)^.portVersion) = kIsColorPort) THEN isColor := TRUE ELSE isColor := FALSE; IF (ControlHandle(itemHandle)^^.contrlHilite <> kCntrlActivate) THEN BEGIN {control is dimmed, so draw gray default button outline} newGray := FALSE; IF isColor THEN BEGIN GetBackColor(bgColor); GetForeColor(fgSaveColor); newfgColor := fgSaveColor; {get the device on which this dialog box is displayed} targetDevice := MyGetDeviceFromRect(ControlHandle(itemHandle)^^.contrlRect); {use the gray defined by the display device} newGray := GetGray(targetDevice, bgColor, newfgColor); END; IF newGray THEN RGBForeColor(newfgColor) ELSE PenPat(gray); PenSize(kButtonFrameSize, kButtonFrameSize); FrameRoundRect(itemRect, buttonOval, buttonOval); IF isColor THEN RGBForeColor(fgSaveColor); END ELSE {control is active, so draw default button outline in black} BEGIN PenPat(black); PenSize(kButtonFrameSize, kButtonFrameSize); FrameRoundRect(itemRect, buttonOval, buttonOval); END; SetPenState(curPen); SetPort(oldPort); END;Listing 6-17 usesGetDialogItem
to get the Spell Check button and then uses
several QuickDraw routines to draw a black outline around that button's display rectangle when the button is active. If the button is inactive (that is, dimmed),MyDrawDefaultButtonOutline
draws a gray outline.Before drawing a gray outline,
MyDrawDefaultButtonOutline
determines whether the dialog box uses a color graphics port. As explained in "Including Color in Your Alert and Dialog Boxes" beginning on page 6-75, you can supply a dialog box with a color graphics port by creating a dialog color table ('dctb'
) resource with the same resource ID as the dialog resource. If the dialog box uses a color graphics port,MyDrawDefaultButtonOutline
uses the Color QuickDraw functionGetGray
to return a blended gray based on the foreground and background colors. ThenMyDrawDefaultButtonOutline
uses this gray for outlining the dimmed default button. Otherwise,MyDrawDefaultButtonOutline
uses the QuickDraw procedurePenPat
to draw a gray outline on black-and-white monitors.