Important: The information in this document is obsolete and should not be used for new development.
Determining and Changing Control Settings
Using either the control resource or the parameters to theNewControl
function, your application specifies a control's various default values--such as its current setting and minimum and maximum settings--when it creates the control.When the user clicks a control, however, your application often needs to determine
the current setting and other possible values of that control. When the user clicks a checkbox, for example, your application must determine whether the box is checked before your application can decide whether to clear or draw a checkmark inside the checkbox. When the user moves the scroll box, your application needs to determine what part of the document to display.Applications must adjust some controls in response to events other than mouse events in the controls themselves. For example, when the user resizes a window, your application must use the Control Manager procedures
MoveControl
andSizeControl
to move and resize the scroll bars appropriately.Your application can use the
GetControlValue
function to determine the current setting of a control, and it can use theGetControlMaximum
function to determine a control's maximum setting.You can use the
SetControlValue
procedure to change the control's setting and redraw the control accordingly. You can use theSetControlMaximum
procedure to change a control's maximum setting and to redraw the indicator or scroll box to reflect the new setting.In response to user action involving a control, your application often needs to change the setting and possibly redraw the control. When the user clicks a checkbox, for example, your application must determine whether the checkbox is currently selected or not, and then switch its setting. When you use
SetControlValue
to switch a checkbox setting, the Control Manager either draws or removes the X inside the checkbox, as appropriate. When the user clicks a radio button, your application must determine whether the radio button is already on and, if not, turn the previously selected radio button off and turn the newly selected radio button on.Figure 5-15 on page 5-31 shows a checkbox in the Play Sounds window. When the user clicks the checkbox to turn it on, the application adds a drum roll to the sound it plays whenever the user clicks the Play button.
Listing 5-13 shows the application-defined routine
DoDrumRollCheckBox
, which responds to a click in a checkbox. This routine uses theGetControlValue
function to determine the last value of the checkbox and then uses theSetControlValue
procedure to change it. TheGetControlValue
function returns a control's current setting, which is stored in thecontrlValue
field of the control record. TheSetControlValue
procedure sets thecontrlValue
field to the specified value and redraws the control to reflect the new setting. (For checkboxes and radio buttons, the value 1 fills the control with the appropriate mark, and the value 0 removes the mark. For scroll bars,SetControlValue
redraws the scroll box at the appropriate position along the scroll bar. For a pop-up menu,SetControlValue
displays in its pop-up box the name of the menu item corresponding to the specified value.)Listing 5-13 Responding to a click in a checkbox
PROCEDURE DoDrumRollCheckBox (mouse: Point; control: ControlHandle); VAR checkbox:Integer; BEGIN IF TrackControl(control, mouse, NIL) <> 0 THEN {user clicks checkbox} BEGIN checkbox := GetControlValue(control); {get last value of checkbox} checkbox := 1 - checkbox; {toggle value of checkbox} SetControlValue(control, checkbox); {set checkbox to new value} IF checkbox = 1 THEN {the checkbox is checked} gPlayDrumRoll := TRUE {play a drum roll next time user clicks Play} ELSE gPlayDrumRoll := FALSE; END; END;TheDoDrumRollCheckBox
routine usesTrackControl
to determine which control the user selects. WhenTrackControl
reports that the user clicks the checkbox,DoDrumRollCheckBox
usesGetControlValue
to determine whether the user last selected the checkbox (that is, whether the control has a current setting of 1) or deselected it (in which case, the control has a current setting of 0). By subtracting the control's current setting from 1,DoDrumRollCheckBox
toggles to a new setting
and then usesSetControlValue
to assign this new setting to the checkbox. TheSetControlValue
procedure changes the current setting of the checkbox and redraws it appropriately, by either drawing an X in the box if the new setting of the control is 1 or removing the X if the new setting of the control is 0.Listing 5-4 on page 5-20 shows the control resources that specify a window's scroll bars, and Listing 5-5 on page 5-21 shows an application's
DoNew
routine for creating a document window with these scroll bars. This routine uses theGetNewControl
function to create the scroll bars and then calls an application-defined routine,MyAdjustScrollBars
. Listing 5-14 showsMyAdjustScrollBars
, which in turn
calls other application-defined routines that determine the proper sizes, locations,
and maximum settings of the scroll bars.Listing 5-14 Adjusting scroll bar settings and locations
PROCEDURE MyAdjustScrollBars (window: WindowPtr; resizeScrollBars: Boolean); VAR myData: MyDocRecHnd; BEGIN myData := MyDocRecHnd(GetWRefCon(window)); HLock(Handle(myData)); WITH myData^^ DO BEGIN HideControl(vScrollBar); {hide the vertical scroll bar} HideControl(hScrollBar); {hide the horizontal scroll bar} IF resizeScrollBars THEN {move and size if needed} MyAdjustScrollSizes(window); MyAdjustScrollValues(window, NOT resizeScrollBars); ShowControl(vScrollBar); {show the vertical scroll bar} ShowControl(hScrollBar); {show the horizontal scroll bar} END; HUnLock(Handle(myData)); END; {of MyAdjustScrollbars}When calling theDoOpen
routine to open an existing document in a window,
SurfWriter also uses thisMyAdjustScrollBars
procedure to size and adjust the
scroll bars. When the user changes the window's size, the SurfWriter application
usesMyAdjustScrollBars
again.The
MyAdjustScrollBars
routine begins by getting a handle to the window's document record, which stores handles to the scroll bars as well as other relevant data about the document. (See the chapter "Window Manager" in this book for information about creating your application's own document record for a window.)Before making any adjustments to the scroll bars,
MyAdjustScrollBars
passes the handles to these controls to the Control Manager procedureHideControl
, which makes the controls invisible. TheMyAdjustScrollBars
routine then calls another application-defined procedure,MyAdjustScrollSizes
(shown in Listing 5-24 on page 5-61), to move and resize the scroll bars appropriately. After calling yet another application-defined procedure,MyAdjustScrollValues
, to set appropriate current and maximum settings for the scroll bars,MyAdjustScrollBars
uses the Control Manager procedureShowControl
to display the scroll bars in their new locations.Listing 5-15 shows how the
MyAdjustScrollValues
procedure calls another application-defined routine,MyAdjustHV
, which uses Control Manager routines to assign appropriate settings to the scroll bars.Listing 5-15 Assigning settings to scroll bars
PROCEDURE MyAdjustScrollValues (window: WindowPtr); VAR myData: MyDocRecHnd; BEGIN myData := MyDocRecHnd(GetWRefCon(window)); HLock(Handle(myData)); WITH myData^^ DO BEGIN MyAdjustHV(TRUE, vScrollBar, editRec); MyAdjustHV(FALSE, hScrollBar, editRec); END; HUnLock(Handle(myData)); END; {of MyAdjustScrollValues}To prevent the user from scrolling past the edge of the document and seeing a blank window, you should limit the scroll bars' maximum settings, as illustrated in Figure 5-6 on page 5-9. If the window is larger than the document (which can easily happen with small documents on large monitors), your application should make the maximum scroll bar settings identical to their minimum settings. In this case, the Control Manager then makes the scroll bars inactive, which is appropriate when all the information fits in
the window.Listing 5-16 shows the application-defined
MyAdjustHV
procedure, used for adjusting the current and maximum settings for a scroll bar. When passedTRUE
in theisVert
parameter,MyAdjustHV
calculates and adjusts the maximum and current settings for the vertical scroll bar; when passedFALSE
, it calculates and adjusts those settings for the horizontal scroll bar.In this example, the document consists of monostyled text stored in a TextEdit edit record. The
viewRect
field of a TextEdit edit record specifies the rectangle where the text is visible; becauseviewRect
already excludes the scroll bar regions,MyAdjustHV
does not need to subtract the scroll bar regions from the window height or width when calculating the maximum settings for these scroll bars. (For more information about TextEdit in general and the edit record in particular, see Inside Macintosh: Text.)Listing 5-16 Adjusting the maximum and current settings for a scroll bar
PROCEDURE MyAdjustHV (isVert: Boolean; control: ControlHandle; editRec: TEHandle); VAR oldValue, oldMax, width: Integer; max, lines, value: Integer; BEGIN {calculate new maximum and current settings for the vertical or } { horizontal scroll bar} oldMax := GetControlMaximum(control); oldValue := GetControlValue(control); MyGetDocWidth(width); IF isVert THEN {adjust max setting for the vertical scroll bar} BEGIN lines := editRec^^.nLines; {since nLines isn't right if the last character is a carriage } { return, check for that case} IF Ptr(ORD(editRec^^.hText^) + editRec^^.teLength - 1)^ = kCRChar THEN lines := lines + 1; max := lines - ((editRec^^.viewRect.bottom - editRec^^.viewRect.top) DIV editRec^^.lineHeight); END ELSE {adjust max setting for the horizontal scroll bar} max := width - (editRec^^.viewRect.right - editRec^^.viewRect.left); IF max < 0 THEN max := 0; {check for negative settings} SetControlMaximum(control, max); {set the max value of the control} IF isVert THEN {adjust current setting for vertical scroll bar} value := (editRec^^.viewRect.top - editRec^^.destRect.top) DIV editRec^^.lineHeight ELSE {adjust current setting for the horizontal scroll bar} value := editRec^^.viewRect.left - editRec^^.destRect.left; IF value < 0 THEN value := 0 ELSE IF value > max THEN value := max; {don't allow current setting to be greater than the } { maximum setting} SetControlValue(control, value); END; {of MyAdjustHV}TheMyAdjustHV
routine first uses theGetControlMaximum
andGetControlValue
functions to determine the maximum and current settings for the scroll bar
being adjusted.Then
MyAdjustHV
calculates a new maximum setting for the case of a vertical scroll bar. Because the window displays a text-only document,MyAdjustHV
uses thenLines
field of the edit record to determine the total number of lines in--and hence, the length of--the document. ThenMyAdjustHV
subtracts the calculated height of the window from the length of the document, and makes this value the maximum setting for the vertical scroll bar.To calculate the total height in pixels of the window,
MyAdjustHV
begins by subtracting the top coordinate of the view rectangle from its bottom coordinate. (The upper-left corner of a window is normally at point [0,0]; therefore the vertical coordinate of a
point at the bottom of a rectangle has a larger value than a point at the top of the rectangle.) ThenMyAdjustHV
divides the pixel height of the window by the value of
the edit record'slineHeight
field, which for monostyled text specifies the document's line height in pixels. By dividing the window height by the line height of the text,MyAdjustHV
determines the window's height in terms of lines of text.The
MyAdjustHV
routine uses another application-defined routine,MyGetDocWidth
,
to determine the width of the document. To calculate the width of the window,MyAdjustHV
subtracts the left coordinate of the view rectangle from its right coordinate. By subtracting the window width from the document width,MyAdjustHV
derives the maximum setting for the horizontal scroll bar.For both vertical and horizontal scroll bars,
MyAdjustHV
assigns a maximum setting of 0 whenever the window is larger than the document--for instance, when a window is created for a new document that contains no data yet. In this case,MyAdjustHV
assigns the same value, 0, to both the maximum and current settings for the scroll bar. The standard control definition function for scroll bars automatically makes a scroll bar inactive when its minimum and maximum settings are identical. This is entirely appropriate, because whenever the user has nowhere to scroll, the scroll bar should be inactive. When you make the maximum setting exceed the minimum, the control definition function makes the scroll bar active again.The
MyAdjustHV
routine then uses the Control Manager procedureSetControlMaximum
to assign the newly calculated maximum settings to either
scroll bar. TheSetControlMaximum
procedure revises the control to reflect the new maximum setting; for example, if the user deletes a large portion of the document, thereby reducing the maximum setting,SetControlMaximum
moves the scroll box
to indicate the new position relative to the smaller document.When the user adds information to or removes information from a document or adjusts its window size, your application may need to adjust the current setting of the scroll bar as well. The
MyAdjustHV
routine calculates a new current setting for the control and then usesSetControlValue
to assign that setting to the control as well as to reposition the scroll box accordingly.The destination rectangle, specified in the
destRect
field of the edit record, is the rectangle in which the text is drawn, whereas the view rectangle is the rectangle in which the text is actually visible. By subtracting the top coordinate of the destination rectangle from the top coordinate of the view rectangle, and dividing the result by the line height,MyAdjustHV
derives the number of the line currently displayed at the top of the window. This is the line numberMyAdjustHV
uses for the current setting of the vertical scroll bar.To derive the current setting of the horizontal scroll bar in terms of pixels,
MyAdjustHV
subtracts the left coordinate of the destination rectangle from the left coordinate of the view rectangle.