MACINTOSH C: A Hobbyist's Guide To Programming the Mac OS in C
Version 2.3
© 2000 K. J. Bricknell

INTRODUCTION TO CONTROLS
A link to the associated demonstration program listings is at the bottom of this page

Introduction
Prior to the introduction of Mac OS 8 and the Appearance Manager, the system software provided for only a limited range of controls (specifically, buttons, checkboxes, radio buttons, pop-up menus, and scroll bars) and the creation and handling of these desktop objects was relatively simple and straightforward. Mac OS 8 and the Appearance Manager, however, ushered in a very wide range of additional controls, extended the capabilities of the old controls, and provided a generally richer control environment. The result is that the subject of controls is now considerably more involved; accordingly, this chapter constitutes an introduction to controls only and addresses only the more basic controls. All but one of the remaining controls will be addressed at Chapter 14 - More on Controls. The remaining control (the list box control) will be addressed at Chapter 20 - Lists and Custom List Definition Functions.
You can use the Control Manager to create and manage controls. An alternative method is to use the Dialog Manager to more easily create and manage controls in dialog boxes and alert boxes. In this latter case, the Dialog Manager works with the Control Manager behind the scenes. The creation and handling of controls in dialog boxes and alert boxes will be addressed at Chapter 8 - Dialogs and Alerts and in the demonstration program associated with Chapter 14 - More on Controls. The creation and handling areas of this chapter are limited to the use of the Control Manager to create and handle controls in document windows.
Every control you create must be associated with a particular window. All the controls for a window are stored in a control list, a handle to which is stored in the controlList field of the window's window structure.
Standard Controls
The term standard controls refers to controls whose control definition functions (see below) are provided by the system software. The term custom controls refers to controls that you provide yourself via a custom control definition function.
Historical Note
Prior to the introduction of Mac OS 8 and the Appearance Manager. It was often necessary to provide your own custom controls (for example, slider controls). However, the large range of controls now provided by the system software means that it is all but inconceivable that you will ever need to create a custom control. A further consideration is the matter of Appearance-compliance. All of the new and revised controls provided by the system are Appearance-compliant. A non-Appearance-compliant custom control will create visual disharmony on the desktop, a situation much to be avoided.
|
Available Appearance-Compliant Standard Controls
The complete range of available standard controls, all of which are Appearance-compliant, is as follows. . (Those control types and variants which existed prior to the introduction of Mac OS 8 and the Appearance Manager, and which have been revised so as to be Appearance-compliant, appear in light blue. Those control types and variants introduced with Mac OS 8 and the Appearance Manager appear in black. Those additional types and variants introduced with Mac OS 8.5 appear in dark blue.)
| Control |
Description |
Variants |
| Push button |
A control that appears on the screen as a rounded rectangle with a title centred inside. When the user clicks a push button, the application performs the action described by the button's title. Button actions are usually performed instantaneously. Examples include completing operations defined by a dialog box and acknowledging an error message in an alert box. |
With title only. With colour icon to left of title. With colour icon to right of title. |
| Checkbox |
A control that appears onscreen as a small square with an accompanying title. A checkbox displays one of three settings: on (indicated by a checkmark inside the box), off, or mixed (indicated by a dash inside the box). |
Non-auto-toggling. Auto-toggling |
| Radio button |
A control that appears onscreen as a small circle. A radio button displays one of three settings: on (indicated by a black dot inside the circle), off, or mixed (indicated by a dash inside the circle). A radio button is always a part of a group of related radio buttons in which only one button can be on at a time. |
Non-auto-toggling. Auto-toggling |
| Scroll bar |
A control with which the user can change the portion of a document displayed within a window. A scroll bar is a light gray rectangle with scroll arrows at each end. Windows can have a horizontal scroll bar, a vertical scroll bar, or both. A vertical scroll bar lies along the right side of a window. A horizontal scroll bar runs along the bottom of a window. Inside the scroll bar is a rectangle called the scroll box. The rest of the scroll bar is called the gray area. The user can move through a document by manipulating the parts of the scroll bar. |
Without live feedback. With live feedback. |
| Pop-up menu button |
A control that is used to display a menu elsewhere than in the menu bar. |
Fixed width. Variable width. Add resource. Use window font. |
| Bevel button |
A button containing a self-descriptive icon, picture, text, or any combination of the three, that performs an action when pressed. |
With small bevel. With normal bevel. With large bevel. The above with a pop-up menu either to the right or below. |
| Slider |
A control that displays a range of values, magnitudes, or positions. A horizontally- and vertically-mobile indicator is used to increase or decrease the value. |
Without live feedback. With live feedback. With tick marks. With directional indicator. With non-directional indicator. |
| Disclosure triangle |
A triangular control governing how items are displayed in a list. The disclosure triangle can point in two directions: right and down. When the disclosure triangle points to the right, one item is displayed in the list. When the arrow points downward, the original item and its subitems are displayed in the list. |
Right-facing. Left-facing. Right-facing, auto-tracking. Left-facing, auto-tracking. |
| Progress indicator |
A control indicating that a lengthy operation is occurring. Two types of progress indicators can be used: an indeterminate progress indicator reveals that an operation is occurring but does not indicate its duration; a determinate progress indicator displays how much of the operation has been completed. |
(One variant only. However, the progress indicator can be made determinate or non-determinate via a call to SetControlData.) |
| Little arrows |
Up- and down-arrows accompanying a text box that contains a value, such as a date. Clicking the up arrow increases the value displayed. Clicking the down arrow decreases the value displayed. |
(One variant only.) |
| Asynchronous (or chasing) arrows |
A control which indicates through a simple animation that a background process is in progress. |
(One variant only.) |
| Tab |
A control that appears as a row of folder tabs on top of a pane. It allows multiple panes to appear in the same window. |
Normal. Small. |
| Separator line |
A control that draws a vertical or horizontal line used to visually separate groups of controls. |
(One variant only.) |
| Primary group box |
A control that consists of a rectangular two-pixel-wide frame which may or may not contain a title. It is used to provide a well-defined area in a dialog box into which text, pictures, icons or other controls can be embedded. |
With text title. With checkbox title. With pop-up menu button title. |
| Secondary group box |
A control that consists of a rectangular one-pixel-wide frame which may or may not contain a title. It is used to provide a well-defined area in a dialog box into which text, pictures, icons or other controls can be embedded. |
With text title. With checkbox title. With pop-up menu button title. |
| Image well |
A control that is used to display non-text visual content on a white background surrounded by a rectangular frame. |
Without auto-tracking. With auto-tracking. |
| Pop-up arrow |
A control that simply draws the pop-up glyph. |
Large, right-facing. Large, left-facing. Large, up-facing. Large, down-facing. Small, right-facing. Small, left-facing. Small, up-facing. Small, down-facing.
|
| Placard |
A rectangular control used as an information display. |
(One variant only.) |
| Clock |
A control that combines the features of little arrows and an edit text field into a control which displays a date and/or time. |
Displays hours, minutes. Displays hours, minutes, seconds. Displays date, month, year. Displays month, year. |
| User pane |
A general purpose control which can be used as the root control for a window and as an embedder control in which other controls may be embedded. It can also be used to hook in callback functions for drawing, hit testing, etc. |
(One variant only.) |
| Edit text |
A control that appears as a rectangular box in which the user enters text to provide information to an application. |
For windows. For dialog boxes. For passwords. Inline input. |
| Static text |
A control that displays static (unchangeable by the user) text labels in a window. |
(One variant only.) |
| Picture |
A control used to display pictures. |
Tracking. Non-tracking. |
| Icon |
A control used to display icons. |
Tracking. Non-tracking. Icon suite, tracking. Icon suite, non-tracking. All icon types, tracking. All icon types, non-tracking. |
| Window header |
A control that runs along the top of a window's content region and provides information about the window's contents. |
Window header. Window list view header. |
| List box |
A control that combines a rectangular frame, scroll bar(s), and a scrolling list. |
Non-autosizing. Autosizing. |
| Radio Group |
A control that implements a radio button group. |
(One variant only.) |
| Scrolling text box |
A control that implements a scrolling text box. |
Non-auto-scrolling. Auto-scrolling. |
Definition of the Term "Controls"
Prior to the introduction of Mac OS 8 and the Appearance Manager, a control was defined as an "on-screen objects which the user can manipulate to cause an immediate action or to change settings to modify a future action". Given this previous definition, the question arises as to why such objects as, for example, separator lines and window headers are now implemented as controls. On the surface, it may appear that these objects are purely visual entities.
Part of the answer to that question has to do with the matter of Appearance-compliance. For example, using the provided separator line "control" to draw separator lines will ensure that those lines are drawn with the correct appearance, in both the activated and deactivated modes, regardless of which Appearance theme has been chosen by the user.
Another part of the answer has to do with the concept of embedding (see below). The window header control, for example, is not just the visual entity it might at first appear to be; it is actually a control in which other controls may be embedded. (As will be seen, the ability to embed other controls is a powerful new feature of some of the new controls.)
Since many of the new controls are not really controls "which the user can manipulate", a more accurate blanket definition might now be "any element of the user interface that is implemented by a control definition function" (see below).
Controls Addressed in This Chapter
Of the controls listed above, only those which might be termed the basic controls (push buttons, checkboxes, radio buttons, scroll bars, and pop-up menu buttons), together with primary group boxes (text title variant) and user panes, will be addressed in this chapter and its associated demonstration programs. These controls, with the exception of the user pane (which is invisible), are illustrated at Fig 1.
The Control Definition Function
A control definition function (CDEF) determines the appearance and behaviour of a control. Various Control Manager functions call a control's CDEF when they need to perform some control-related action. CDEFs are stored as resources of type 'CDEF'.
Just as a window definition function can describe variations of the same basic window, a CDEF can use a variation code to describe variations of the same control. You specify a particular control with a control definition ID, which is an integer containing the resource ID of the in the upper 12 bits and the variation code in the lower four bits.
The control definition ID is arrived at by multiplying the resource ID by 16 and adding the variation code. The following shows the control definition IDs for the standard controls and variants addressed in this chapter and its associated demonstration programs, together with the derivation of those IDs. (Those variants introduced with Mac OS 8.5 are shown in dark blue.)
CDEF Resource ID |
Variation Code |
Control Definition ID (Value) |
Control Definition ID (Constant) |
| 23 |
0 |
23 * 16 + 0 = 368 |
kControlPushButtonProc |
| 23 |
4 |
23 * 16 + 4 = 374 |
kControlPushButLeftIconProc |
| 23 |
5 |
23 * 16 + 5 = 375 |
kControlPushButRightIconProc |
| 23 |
1 |
23 * 16 + 1 = 369 |
kControlCheckBoxProc |
| 23 |
3 |
23 * 16 + 3 = 371 |
kControlCheckBoxAutoToggleProc |
| 23 |
2 |
23 * 16 + 2 = 370 |
kControlRadioButtonProc |
| 23 |
4 |
23 * 16 + 3 = 372 |
kControlRadioAutoToggleButtonProc |
| 24 |
0 |
24 * 16 + 0 = 384 |
kControlScrollBarProc |
| 24 |
2 |
24 * 16 + 2 = 386 |
kControlScrollBarLiveProc |
| 25 |
0 |
25 * 16 + 0 = 400 |
kControlPopupButtonProc |
| 25 |
1 |
25 * 16 + 1 = 401 |
kControlPopupButtonProc + kControlPopupFixedWidthVariant |
| 25 |
2 |
25 * 16 + 2 = 402 |
kControlPopupButtonProc + kControlPopupVariableWidthVariant |
| 25 |
4 |
25 * 16 + 4 = 404 |
kControlPopupButtonProc + kControlPopupUseAddResMenuVariant |
| 25 |
8 |
25 * 16 + 8 = 408 |
kControlPopupButtonProc + kControlPopupUseWFontVariant |
| 10 |
0 |
10 * 16 + 0 = 160 |
kControlGroupBoxTextTitleProc |
| 16 |
0 |
16 * 16 + 0 = 256 |
kControlUserPaneProc |
Historical Note
With regard to the basic controls, these are the resource IDs and variation codes of the new Appearance-compliant CDEFs first issued with Mac OS 8 and the Appearance Manager. The old CDEFs have resource IDs of 0 (button, checkbox, radio button), 1 (scroll bar), and 63 (pop-up menu), and remain in the System file. The new definition functions are located in the Appearance extension.
|
Note that the one CDEF caters for both horizontal and vertical scroll bars. The CDEF determines whether a scroll bar is vertical or horizontal from the rectangle you specify when you create the control.
The Basic Controls, Primary Group Boxes (Text Title Variant), and User Panes
Push Buttons
You normally use push buttons in alert boxes and dialog boxes. Push buttons typically allow the user to perform actions instantaneously, for example, completing the actions in a dialog box or acknowledging an error in an alert box. In every window or dialog box in which you display push buttons, you should designate one push button as the default push button, that is, the push button the user is most likely to click. (In modal and movable modal alert boxes, the Dialog Manager automatically outlines the default push button (see the default push button at Fig 1); however, your application must outline the push button in modeless dialog boxes.)
Your application should respond to key-down events involving the Enter and Return keys as if the user had clicked the default push button.
Checkboxes
Checkboxes are typically used in dialog boxes so that the user can supply additional information necessary for completing a command. Checkboxes provide alternative choices and act like toggle switches, turning a setting on or off. Each checkbox has a title, which should reflect two clearly opposite states. If you cannot devise a title which clearly implies two opposite states, you might be better off providing two radio buttons.
Non-Auto-Toggling Variant
When the non-auto-toggling variant is being used, and when the user clicks a checkbox in the off state, your application should call SetControlValue to set the control to the on state and place a checkmark in the box (see Fig 1). When the user again clicks the checkbox, your application should call SetControlValue to set the control to the off state and remove the checkmark from the box.
SetControlValue may also be used to place a dash in the box to indicate that the control is in the mixed state (see Fig 1). The mixed state is a special state which indicates that a selected range of items has some in the on state and some in the off state. For example, a text formatting checkbox for bold text would be in the mixed state if a text selection contained both bold and non-bold text.
Historical Note
The mixed state was introduced with Mac OS 8 and the Appearance Manager.
|
Auto-Toggling Variant
When the auto-toggling variant is being used, checkboxes automatically changes between their various states (on, off, and mixed) in response to user actions. Your application need only call the function GetControl32BitValue to get the checkbox's new state. There is no need to programmatically change the control's value after tracking successfully.
Historical Note
The auto-toggling variant was introduced with Mac OS 8.5.
|
Radio Buttons
Like checkboxes, radio buttons retain and display an on or off setting and are typically used inside dialog boxes. Radio buttons represent choices that are related but not necessarily opposite. The user can have only one radio button setting in effect at one time; in other words, radio buttons within a group are mutually exclusive.
A group of radio buttons must comprise at least two radio buttons. Each group must have a label which identifies the kind of choices the group offers and each button must have a title identifying what the radio button does. If you need to display more than seven items, or if the items change as the context changes, you should use a pop-up menu button instead.
Non-Auto-Toggling Variant
When the non-auto-toggling variant is being used, and when the user clicks a radio button in the off state, your application should call SetControlValue to:
- Set that control to the on state and place a black dot in its circle (see Fig 1).
- Set the previously "on" button in the group to the off state and remove the black dot from its circle.
SetControlValue may also be used to place a dash in the circle to indicate that the control is in the mixed state (see Fig 1). The mixed state is a special state which shows that a selected range has a variety of items in the on state. For example, a set of radio buttons for selecting font size might have buttons representing 10- and 12-point sizes. If a passage of text with both 10- and 12-point text was selected, both the 10 and 12 buttons would appear in the mixed state.
Historical Note
The mixed state was introduced with Mac OS 8 and the Appearance Manager.
|
Auto-Toggling Variant
When the auto-toggling variant introduced with Mac OS 8.5 is being used, radio buttons automatically change between their various states (on, off, and mixed) in response to user actions. Your application need only call the function GetControl32BitValue to get the radio button's new state. There is no need to programmatically change the control's value after tracking successfully.
P>
Historical Note
The auto-toggling variant was introduced with Mac OS 8.5.
|
Scroll Bars
Scroll bars change the portion of a document that the user can view within a document's window. A scroll bar is a light gray rectangle with scroll arrows at each end. Inside the scroll bar is a scroll box. The rest of the scroll box is called the gray area. If the user drags the scroll box, clicks a scroll arrow or clicks in the gray region, your application scrolls the document accordingly.
As previously stated, the CDEF for scroll bars supports two variants. The only difference between the two variants is that one supports live feedback and the other does not. In the case of scroll bars, live feedback (a generic term) may be used to perform live scrolling of a document in a window. Live scrolling means that, when the user attempts to drag the scroll box, the scroll box moves and the document scrolls as the user moves the mouse. (Without live scrolling, only a ghosted image of the scroll box moves. In addition, the document is only scrolled, and the scroll box proper is only redrawn at its new location, when the user releases the mouse button.)
Historical Note
The live feedback capability was introduced with Mac OS 8 and the Appearance Manager. |
Scroll Arrows and Gray Area
When the scroll arrows are clicked, your application should move the scroll box the appropriate distance in the direction of the arrow being clicked and scroll the window contents accordingly. Each click should move the window contents one unit in the chosen direction. (In a text document, a unit would typically be one line of text.)
When the gray area is clicked above the scroll box, your application should move the document up so that the bottom line of the previous view is at the top of the new view, and it should move the scroll box accordingly. A similar, but downward movement, should occur when the user clicks in the gray area below the scroll box.
Scroll Box
Live Feedback Variant Not Used. When the live feedback variant is not being used, and when the user drags the scroll box, the Control Manager redraws the scroll box proper in its new position, and sets the control's value accordingly, when the user releases the mouse button. You must then ascertain the position (that is, the value) of the control box and, using this value, display the appropriate portion of the document.
Live Feedback Variant Used. When the live feedback variant is being used, and when the user drags the scroll box, the Control Manager continually redraws the scroll box, and continually returns the control's position (that is, its value) as the scroll box moves. Once again, your application uses this value to display the appropriate portion of the document.
Proportional Scroll Boxes
A proportional scroll box is one whose height (vertical scroll bars) or width (horizontal scroll bars) varies in relation to the height/width of the scroll bar so as to visually represent the proportion of the document visible in the window.
Under Mac OS 8.5 and later, if the user selects Smart Scrolling on in the Options tab in the Appearance control panel, your application's scroll boxes will appear as proportional scroll boxes provided that you pass the size of the view area, in whatever units the scroll bar uses, to the function SetControlViewSize. The system automatically handles resizing the scroll box once your application supplies this information.
Historical Note
Proportional scroll boxes were introduced with Mac OS 8.5. |
The following functions, introduced with Mac OS 8.5, are relevant to proportional scroll boxes:
| Function |
Description |
| GetControlViewSize |
Obtains the size of the content to which a control's size is proportioned. |
| SetControlViewSize |
Informs the Control Manager of the size of the content to which a control's size is proportioned. |
Pop-Up Menu Buttons
Pop-up menu buttons provide the user with a simple way to choose from a list of choices. As an alternative to a group of radio buttons, a pop-up menu button is useful for specifying a group of settings or values that number five or more, or whose settings or values might change. Like the items in a group of radio buttons, the items in a pop-up menu button's menu should be mutually exclusive.
Primary Group Boxes (Text Title Variant)
A primary group box (text title variant) is a control that consists of a rectangular two-pixel-wide frame which may or may not contain a title. Group boxes are used to associate, isolate, and distinguish groups of related controls, such as a group of radio buttons.
The primary group box is an embedder control (see below), meaning that you can embed other controls, such as radio buttons, checkboxes, and pop-up menu buttons, within it.
User Panes
The user pane is unique amongst the family of controls in that it has no visual representation. It has two main uses:
- Like the primary group box, it can be used as an embedder control, that is, other controls may be embedded within it.
- It provides a way to hook in application-defined functions, known as user pane functions, which perform actions such as drawing, hit testing, etc.
Activating, Deactivating, Hiding, and Showing Controls
Activating and Deactivating Controls
A control can be either active or inactive. Whenever it is inappropriate for your application to respond to a mouse-down event in a control, you should make it inactive. The Control Manager continues to display inactive controls so that they remain visible, but in a dimmed state which indicates their inactive status to the user. The Control Manager displays inactive basic controls and inactive primary group boxes as shown at Fig 2.
Activating and Deactivating Controls Other Than Scroll Bars
You use ActivateControl and DeactivateControl to make push buttons, checkboxes, radio buttons, pop-up menu buttons and primary group boxes active and inactive. You should make these controls inactive when:
- They are not relevant to the current context.
- The window in which they reside is not the active window.
Your application can ascertain whether a control is currently active or inactive using IsControlActive.
Historical Note
Prior to Mac OS 8 and the Appearance Manager, the HiliteControl function was used for this purpose. HiliteControl has other uses for which it may still be used; however it should not now be used to activate and deactivate controls.
|
Activating and Deactivating Scroll Bars
Scroll bars become irrelevant to the current context when the document being displayed is smaller than the window in which it is being displayed. To make a scroll bar inactive in this case, you typically use SetControlMaximum to make the scroll bar's maximum value (see below) equal to its minimum value (see below), which causes the Control Manager to automatically make the scroll bar inactive and display it in the inactive state. To make the scroll bar active again, SetControlMaximum should be used to set its maximum value larger than its minimum value.
Hiding and Showing Controls
HideControl may be used to hide a control. HideControl erases a control by filling its enclosing rectangle with the owning window's background pattern.
ShowControl may be used to show a control. ShowControl makes the control visible and immediately draws the control within its window without using your window's standard updating mechanism.
SetControlVisibility may be used to both hide and show a control. With regard to showing a control, this function differs from ShowControl in that the option is available to "show" the control without redrawing it immediately.
Your application can ascertain whether a control is currently hidden or visible using IsControlVisible.
Historical Note
SetControlVisibility and IsControlVisible were introduced with Mac OS 8 and the Appearance Manager.
|
Visual Feedback From the Basic Controls
In response to a mouse-down event in a basic control, your application should call either TrackControl or HandleControlClick. These functions provide visual feedback when a mouse-down occurs in an active control by:
- Displaying push buttons, checkboxes and radio buttons in their pressed mode.
- Displaying and highlighting the items in pop-up menu buttons.
- Highlighting the scroll arrows in scroll bars.
- Moving the scroll box (live feedback variant of the scroll bar CDEF being used) or moving a ghosted image of the scroll box (live feedback variant not being used) when the user drags it.
Historical Note
HandleControlClick was introduced with Mac OS 8 and the Appearance Manager. It is identical to TrackControl except that it allows modifier keys to be passed in its third parameter. Some of the new controls, such as edit text fields and list boxes, require the ability for modifier keys to be passed in. If you use HandleControlClick with controls for which modifier keys are irrelevant, simply pass 0 in the inModifiers parameter.
|
Embedding Controls
In addition to providing a large number of additional control types, Mac OS 8 and the Appearance Manager introduced a richer environment for controls. The innovation of specific relevance to this chapter is control embedding. As previously stated, this involves the embedding of a control (or, more usually, a group of controls) in another control.
The Root Control
To embed controls in a window, you must first create a root control for that window. The root control, which is implemented as a user pane control, is the container for all other window controls and is at the base of what is known as the embedding hierarchy. In document windows, you create the root control by calling CreateRootControl. The root control may be retrieved by calling GetRootControl.
Once you have created a root control, new controls will be automatically embedded in the root control when they are created. One advantage of such embedding is that, when you wish to activate and deactivate all of the window's controls on window activation and deactivation, you can do so by simply activating and deactivating the root control. (If the root control did not exist, you would have to activate and deactivate all of the window's controls individually.) You can also hide and show all of the window's control by simply hiding and showing the root control.
Other Embedders
Certain other controls also have embedding capability. One such embedder control is the primary group box. This means that you can embed, say, a group of radio buttons in a primary group box (which would, in turn, be already automatically embedded in the root control), an arrangement which is illustrated conceptually at Fig 3. By acting on the group box alone, you can then activate, deactivate, hide, show, and move all four controls as a group.
EmbedControl may be used to embed a control in another (embedder) control. However, where the control to be embedded is visually contained by the embedder, as is the case with the radio buttons in Fig 3, AutoEmbedControl would be more appropriate.
Other Advantages of Embedding
Drawing Order
As controls are created by your application, they are added to the head of the window's control list. When those controls are drawn in the absence of an embedding hierarchy, the Control Manager starts from the top of the control list, drawing the controls in the opposite order to the order in which it they were created.
In the example at Fig 3, assume that there is no embedding hierarchy and that the radio buttons are created after the group box. This means that the group box will be drawn after the radio buttons, thus obscuring the radio buttons. An embedding hierarchy, however, enforces drawing order by drawing the embedding control before its embedded controls regardless of which is created first.
Hit Testing
Hit-testing is the process of testing whether a control is under the cursor at the time of a mouse-down event, and of identifying that control. For situations where controls are visually contained by other controls, an embedding hierarchy enforces orderly hit-testing by forcing an "inside-out" hit test aimed at determining the most deeply nested control that is hit by the mouse.
Latency
Latency pertains to the ability of the Control Manager to remember the activation and visibility status of an embedded control when its embedder is cycled between activated and deactivated, or between visible and hidden.
For example, assume that the radio button labelled White at Fig 3 has been separately deactivated by the application. When the primary group box is deactivated, the two remaining radio buttons will also be deactivated. When the primary group box is again enabled, the Control Manager remembers that the radio button labelled white was previously deactivated, and ensures that it remains in that mode.
Getting and Setting Control Data
Another refinement introduced with Mac OS 8 and the Appearance Manager was read and write access to the various attributes of a control. Essentially, this is a mechanism that allows the outside world to access a control's specialised data without exposing how that data is stored. It allows you to easily set and get control fonts, tell the push button CDEF to draw the default outline around a default push button, and many other useful things.
Each piece of information that a particular CDEF allows access to is referenced by a tag, which is a constant that is meaningful to the CDEF and which represents the data in question. Each tagged piece of data can be of any data type, such as a menu handle or a structure.
Control data tag constants are passed in the third parameter of the getter and setter functions SetControlData and GetControlData. The control data tag constants relevant to the basic controls are as follows:
| Control Data Tag Constant |
Meaning and Data Type Returned or Set |
| kControlPushButtonDefaultTag |
Tells Appearance-compliant push buttons whether to draw a default ring, or returns whether the Appearance Manager has drawn a default ring, for the push button. Data type returned or set: Boolean |
| kControlPushButtonCancelTag |
Gets or sets whether a given push button in a dialog or alert should be drawn with the appearance-specific adornments for a Cancel button. Data type returned or set: Boolean. Default is false. |
| kControlPopupButtonMenuHandleTag |
Gets or sets the menu handle for a pop-up menu. Data type returned or set: MenuHandle |
| kControlPopupButtonMenuIDTag |
Gets or sets the menu ID for a pop-up menu button. Data type returned or set: SInt16 |
| kControlPopupButtonExtraHeightTag |
Gets or sets the amount of extra white space in a pop-up menu button. Data type returned or set: SInt16. Default is 0. |
| kControlGroupBoxTitleRectTag |
Get the rectangle that contains the title of a group box (and any associated control, such as a checkbox). Data type returned or set: Rect |
Historical Note
Calling SetControlData with the kControlPushButtonDefaultTag tag constant greatly simplifies the task of drawing the default ring around the default push button. Prior to Mac OS 8 and the Appearance Manager, your application had to provide its own function to do this.
kControlPushButtonCancelTag, kControlPopupButtonExtraHeightTag, and kControlGroupBoxTitleRectTag were introduced with Mac OS 8.5.
|
The Control Structure
The Control Manager stores information about a control in a control structure. A control structure is defined by the data type ControlRecord:
struct ControlRecord
{
ControlHandle nextControl; // Next Control.
WindowPtr contrlOwner; // Control's window.
Rect contrlRect; // Rectangle.
UInt8 contrlVis; // 255 if visible, else 0.
UInt8 contrlHilite; // Highlight state.
SInt16 contrlValue; // Current setting.
SInt16 contrlMin; // Minimum Setting.
SInt16 contrlMax; // Maximum setting.
Handle contrlDefProc; // Control definition function.
Handle contrlData; // Data used by contrlDefProc.
ControlActionUPP contrlAction; // Action function.
SInt32 contrlRfCon; // Reference constant.
Str255 contrlTitle; // Title.
};
typedef struct ControlRecord ControlRecord;
typedef ControlRecord *ControlPtr;
typedef ControlPtr *ControlHandle;
Creating Your Application's Basic Controls
You typically create controls from resources of type 'CNTL', though you can create controls programmatically using the function NewControl.
'CNTL' Resources
When creating resources with Resorcerer, it is advisable that you refer to a diagram and description of the structure of the resource and relate that to the various items in the Resorcerer editing windows. Accordingly, the following describes the structure of the 'CNTL' resource.
Structure of a Compiled 'CNTL' Resource
Fig 4 shows the structure of a compiled 'CNTL' resource and how it "feeds" the control structure.
The following describes the main fields of the 'CNTL' resource:
| Field |
Description |
| INITIAL RECTANGLE |
The rectangle, specified in coordinates local to the window, that encloses the control and thus determines its size and location. |
| INITIAL VALUE |
The initial value for the control. (See Values for Controls, below). |
| VISIBILITY |
The visibility of the control. If this field contains the value true, GetNewControl draws the control immediately, without using the application's standard updating mechanism for windows. If this field contains false, the application may use ShowControl when it is prepared to display the control. |
| MAXIMUM VALUE |
The maximum value of the control. (See Values for Controls, below). |
| MINIMUM VALUE |
The minimum value for the control. (See Values for Controls, below). |
| CONTROL DEFINITION ID |
The control definition ID, which the Control Manager uses to determine the CDEF for the control. (See The Control Definition Function, above). |
| REFERENCE VALUE |
The control's reference value, which is set up and used only by the application (except when the control is the add resource variant of the pop-up menu button, in which case this field is used to specify the resource type). |
| TITLE |
For controls that need a title, the string for that title. For controls that do not need or do not use titles, an empty string. |
Values For Controls
The following lists the initial, minimum, and maximum value settings for the basic controls and the primary group box:
| Control |
Initial Value |
Minimum Value |
Maximum Value |
| Push button |
0 |
0 |
1 |
| Checkbox |
0 (initially off), or 1 (initially on), or 2 (initially in mixed state). |
0 |
1, or 2 if mixed state checkboxes are to be used. |
| Radio button |
0 (initially off), or 1 (initially on), or 2 (initially in mixed state). |
0 |
1, or 2 if mixed state radio buttons are to be used. |
| Scroll bar |
Whatever initial value is appropriate (between the minimum and maximum settings). |
Whatever minimum value is appropriate. (See Creating Scroll Bars, below.) The value must be between -32768 and 32768. |
Whatever maximum value is appropriate. (See Creating Scroll Bars, below.) The value must be between -32768 and 32768. When the maximum setting is equal to the minimum setting, the CDEF makes the scroll bar inactive. When the maximum setting is greater than the minimum setting, the CDEF makes the scroll bar active. |
| Pop-up menu button |
A combination of values which instructs the Control Manager how to draw the control's title. (See Pop-up Menu Button Title Style Constants, below.) |
Resource ID of the 'MENU' resource. |
Width (in pixels) of the title. (See Pop-up Menu Button Title Width, below.) |
| Primary group box |
Ignored if the group box is the text title variant. |
Ignored if the group box is the text title variant. |
Ignored if the group box is the text title variant. |
Note that the title of each of the three value fields is somewhat of a misnomer in the case of the pop-up menu button.
Creating 'CNTL' Resources Using Resorcerer
Fig 5 shows a 'CNTL' resource being created with Resorcerer.
Creating Controls
GetNewControl and NewControl are used to create new controls in a document window. You typically use GetNewControl, which takes a 'CNTL' resource ID and a pointer to the window, creates a control structure from the information in the resource, adds the control structure to the control list for your window, and returns a handle to the control.
If the 'CNTL' resource specifies that a control is initially visible, the Control Manager uses the CDEF to draw the control. (The Control Manager draws the control immediately and does not wait for the window updating mechanism.) If the 'CNTL' resource specifies that the control is to be initially invisible, ShowControl may be used to draw the control when required.
Note that when you use the Dialog Manager to implement push buttons, radio buttons, checkboxes or pop-up menu buttons in alert boxes or dialog boxes, Dialog Manager functions automatically use Control Manager functions to create the controls for you.
Creating Scroll Bars
The 'CNTL' resource for scroll bars should specify whether the live-feedback variant or the non-live-feedback variant is required. Within the 'CNTL' resource, you typically make the scroll bar invisible, set the initial, minimum and maximum settings to 0 and supply an empty string for the title.
After you create the window, use GetNewControl to create the scroll bar. Then use MoveControl, SizeControl, SetControlMaximum and SetControlValue to adjust the size, location and value settings. (For example, for a window displaying a text document, you would typically calculate the number of lines of text and set the vertical scroll bar's maximum value according to the line count and the window's current height. You would set the control's value according to the part of the document to be initially displayed.) Finally, use ShowControl to display the control bar.
Most applications allow the user to change the size of windows, add information to the document and remove information from the document. It is therefore necessary, in your window handling code, to calculate a changing maximum setting based on the document's current size and its window's current size. For new documents which have no content to scroll, assign an initial value of 0 as the maximum setting (which will, as previously stated, make the scroll bars inactive). Thereafter, your window-handling code should set and maintain the maximum setting.
By convention, a scroll bar for a document window is 16 pixels wide; accordingly, there should be a sixteen-pixel difference between the left and right coordinates of a vertical scroll bar's rectangle and between the top and bottom coordinates of a horizontal scroll bar. (If you do not specify a 16-pixel width, the Control Manager scales the scroll bar to fit the width you specify.) A standard scroll bar for a document window should be at least 48 pixels long to allow room for the scroll arrows and scroll box.
The Control Manager draws one-pixel lines for the rectangle enclosing the scroll bar. As shown at Fig 6, the outside lines of the scroll bar should overlap the inside lines of the window frame.
The following calculations determine the rectangle for a vertical scroll bar for a document window:
 |
Do not include the title bar area in these calculations.
|
| Coordinate |
Calculation |
| Top |
Combined height of any items above the scroll bar - 1. |
| Left |
Width of window - 15. |
| Bottom |
Height of window - 14. |
| Right |
Width of window + 1. |
The following calculations determine the rectangle for a horizontal scroll bar for a document window.
| Coordinate |
Calculation |
| Top |
Height of window - 15. |
| Left |
Combined width of any items to the left of the scroll bar - 1. |
| Bottom |
Height of window + 1. |
| Right |
Width of window - 14. |
The top coordinate of a vertical scroll bar and the left coordinate of a horizontal scroll bar is -1 unless your application uses part of the window's typical scroll bar area for displaying information or specifying additional controls.
Just as the maximum settings change when the user resizes a document's window, so too do the scroll bar's coordinate locations change when the user resizes the window. The initial maximum settings and location, as specified in the 'CNTL' resource, must therefore be changed dynamically by the application as required. Typically, this is achieved by storing handles to each scroll bar in an application-defined document structure associated with the window and then using Control Manager functions to change control settings.
Scroll Bars in Utility Windows. You can also use scroll bars in utility windows (see Fig 7). Size boxes in utility windows are 11-by-11 pixels, and the standard Appearance-compliant scroll bar can be made to fit into this space.
Pop-up Menu Buttons
Pop-up Menu Button Title Style Constants
The constants and values for the initial value for pop-up menu buttons are as follows:
| Constant |
Value |
Meaning |
| popupTitleBold |
0x0100 |
Boldface font style |
| popupTitleItalic |
0x0200 |
Italic font style |
| popupTitleUnderline |
0x0400 |
Underline font style |
| popupTitleOutline |
0x0800 |
Outline font style |
| popupTitleShadow |
0x1000 |
Shadow font style |
| popupTitleCondense |
0x2000 |
Condensed text |
| popupTitleExtend |
0x4000 |
Extended text |
| popupTitleNoStyle |
0x0800 |
Monostyle text |
Pop-up Menu Button Title Width
Fig 8 shows the relationship between the title width and the enclosing rectangle of a pop-up menu box.
Menu Width Adjustment
If the base variant or the variable width variant is being used, and whenever the pop-up menu button is redrawn, the CDEF calls CalcMenuSize to calculate the size of the menu associated with the control. If the sum of the width of the title, the longest item in the menu, the arrows, and a small amount of "white space" is less than the width of the control rectangle, the width of the pop-up button will be reduced for drawing purposes (see Fig 7). If the calculated width is greater than the width of the control rectangle, the longer menu items will be truncated with an added ellipsis so that the drawn pop-up will not exceed the width of the control rectangle.
Menu Items and Control Values
When it creates the control, GetNewControl assigns the item number of the first menu item to the contrlValue field of the control structure and sets the contrlMax field to the number of items in the pop-up menu button. When the user chooses a different menu item, the Control Manager changes the contrlValue field to that item number.
Adding Resource Names as Items
If the add resource variant of the pop-up menu button is being used, the Control Manager coerces the value in the control structure's contrlRfCon field to the type ResType and then uses AppendResMenu to add items of that type. For example, if you specify FONT in the ResType item in the Resorcerer 'CNTL' resource editing window, the CDEF appends a list of fonts installed in the system to the menu specified at the 'MENU' ID item. Note that, after the control has been created, your application can use the contrlRfCon field for whatever purpose it requires.
Setting the Font of a Control's Title
You can set the font of any control's title independently of the system font or window font.
Historical Note
Prior to Mac OS 8 and the Appearance Manager, your only choices were the system font and, if the control had a variant that used it (as did the pop-up menu control), the window font.
|
To set the font of a control's title, you pass a pointer to a control font style structure in the inStyle parameter of the function SetControlFontStyle.
Control Font Style Structure
struct ControlFontStyleRec
{
SInt16 flags;
SInt16 font;
SInt16 size;
SInt16 style;
SInt16 mode;
SInt16 just;
RGBColor foreColor;
RGBColor backColor;
};
typedef struct ControlFontStyleRec ControlFontStyleRec;
typedef ControlFontStyleRec *ControlFontStylePtr;
Field Descriptions
| flags |
A signed 16-bit integer specifying which fields of the structure should be applied to the control (see Control Font Style Flag Constants, below). If none of the flags in the flags field of the structure are set, the control uses the system font unless the control variant kControlUsesOwningWindowsFontVariant has been specified, in which case the control uses the window font. |
| font |
If the kControlUseFontMask bit is set, this field will contain an integer indicating the ID of the font family to use. If this bit is not set, then the system default font is used. A meta font constant can be specified instead (see Meta Font Constants, below). |
| size |
If the kControlUseSizeMask bit is set, this field will contain an integer representing the point size of the text. If the kControlAddSizeMask bit is set, this value will represent the size to add to the current point size of the text. A meta font constant can be specified instead (see Meta Font Constants, below). |
| style |
If the kControlUseStyleMask bit is set, this field will contain an integer specifying which styles to apply to the text. If all bits are clear, the plain font style is used. The bit numbers and the styles they represent are as follows:
| Bit Value |
Style |
| 0 |
Bold |
| 1 |
Italic |
| 2 |
Underline |
| 3 |
Outline |
| 4 |
Shadow |
| 5 |
Condensed |
| 6 |
Extended |
|
| mode |
If the kControlUseModeMask bit is set, this field will contain an integer specifying how characters are drawn in the bit image. (See Chapter 12 - Drawing With QuickDraw for a discussion of transfer modes.) |
| just |
If the kControlUseJustMask bit is set, this field will contain an integer specifying text justification (left, right, centered, or system script direction). |
| foreColor |
If the kControlUseForeColorMask bit is set, this field will contain an RGB (red-green-blue) colour to use when drawing the text. |
| backColor |
If the kControlUseBackColorMask bit is set, this element will contain an RGB (red-green-blue) colour to use when drawing the background behind the text. (Note that, in certain text modes, background colour is ignored.) |
Control Font Style Flag Constants
You can pass one or more of the following control font style flag constants in the flags field of the control font style structure to specify those fields of the structure that are be applied to the control. (The constant shown in dark blue was introduced with Mac OS 8.5.) If none of the flags in of the flags field are set, the control uses the system font unless a control with a variant that uses the window font has been specified.
| Constant |
Value |
Meaning |
| kControlUseFontMask |
0x0001 |
The font field of the control font style structure is applied to the control. |
| kControlUseFaceMask |
0x0002 |
The style field of the control font style structure is applied to the control. This flag is ignored if you specify a meta font value (see Meta Font Constants, below). |
| kControlUseSizeMask |
0x0004 |
The size field of the control font style structure is applied to the control. This flag is ignored if you specify a meta font value (see Meta Font Constants, below). |
| kControlUseForeColorMask |
0x0008 |
The foreColor field of the control font style structure is applied to the control. This flag only applies to static text controls. |
| kControlUseBackColorMask |
0x0010 |
The backColor field of the control font style structure is applied to the control. This flag only applies to static text controls. |
| kControlUseModeMask |
0x0020 |
The text mode specified in the mode field of the control font style structure is applied to the control. |
| kControlUseJustMask |
0x0040 |
The just field of the control font style structure is applied to the control. |
| kControlUseAllMask |
0x00FF |
All flags in this mask will be set except kControlUseAddFontSizeMask. |
| kControlUseAddFontSizeMask |
0x0100 |
The Dialog Manager will add a specified font size to the size field of the control font style structure. This flag is ignored if you specify a meta font value (see Meta Font Constants, below. |
| KControlAddToMetaFontMask |
0x0200 |
The control may use a meta font while also adding other attributes to the font. |
Meta Font Constants
You can use the following meta font constants in the font field of the control font style structure to specify the style, size, and font family of a control's font. You should use these meta font constants whenever possible because the system font can change, depending upon the current theme. If none of these constants are specified, the control uses the system font unless a control with a variant that uses the window font has been specified.
| Constant |
Value |
Meaning In Roman Script System |
| kControlFontBigSystemFont |
0x0001 |
Use the system font. (For the Roman script system, this is Charcoal 12.) |
| kControlFontSmallSystemFont |
0x0002 |
Use the small system font. (For the Roman script system, this is Geneva 10.) |
| kControlFontSmallBoldSystemFont |
0x0004 |
Use the small emphasised system font. (For the Roman script system, this is Geneva 10.) |
Another advantage of using these meta font constants is that you can be sure of getting the correct font on a Macintosh using a different script system, such as kanji.
Updating, Moving, and Removing Controls
Updating Controls
When your application receives an update event for a window containing controls, it should call UpdateControls between the BeginUpdate and EndUpdate calls in its updating function.
Note that when you use the Dialog Man |