TweetFollow Us on Twitter

MACINTOSH C CARBON
MACINTOSH C CARBON: A Hobbyist's Guide To Programming the Macintosh in C
Version 1.0
© 2001 K. J. Bricknell
Go to Contents Go to Program Listing

CHAPTER 7

INTRODUCTION TO CONTROLS

Introduction

On Mac OS 8/9, 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 or two of the remaining controls are addressed at Chapter 14. The list box control is addressed at Chapter 22.

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 dialogs and alerts. In this latter case, the Dialog Manager works with the Control Manager behind the scenes. The creation and handling of controls in dialogs and alerts will be addressed at Chapter 8 and in the demonstration program associated with Chapter 14. The creation and handling areas of this chapter are limited to the use of the Control Manager to create and handle controls in document or utility 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 reference to which is stored in the window's window object.

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.

Available Standard Controls

The complete range of available standard controls is as follows.

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. Examples include completing operations defined by a dialog and acknowledging an error message in an alert.

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 (Mac OS 8/9) or scroller (Mac OS X). The rest of the scroll bar is called the gray area (Mac OS 8/9) or track (Mac OS X). 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 (Mac OS 8/9 only).
With normal bevel.
With large bevel (Mac OS 8/9 only).
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 right or left and down. When the disclosure triangle points to the right or left, 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 bar

A control indicating that a lengthy operation is occurring. Two types of progress bar can be used: an indeterminate progress bar reveals that an operation is occurring but does not indicate its duration; a determinate progress bar displays how much of the operation has been completed.

Progress bars are also used as relevance bars on Mac OS 8/9.

(One variant only. However, the progress bar 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.)

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.

Large, north facing.
Small, north facing.
Large, south facing.
Small, south facing.
Large, east facing.
Small, east facing.
Large, west facing.
Small, west facing.

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 that may or may not contain a title. It is used to provide a well-defined area in a dialog 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 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 surrounded by a rectangular frame.

(One variant only.)

Pop-up arrow

A control that simply draws the pop-up glyph.

Large, east-facing.
Large, west-facing.
Large, north-facing.
Large, south-facing.
Small, east -facing.
Small, west -facing.
Small, north -facing.
Small, south -facing.

Placard

A rectangular control used to delineate an area in which information may be displayed.

(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.

Normal.
For passwords.
For 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 rectangular control that is positioned along the top of a window's content region and which is used to delineate an area in which information may be displayed.

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.

Data Browser

A control that implements a user interface component for browsing (optionally) hiearchical data structures.

Note:This control is not addressed in this book.

Disclosure button

A button used to hide or show specific content. Available on Mac OS X only.

(One variant only)

Edit Unicode text

Similar to the edit text controls, except that it handles Unicode text. Available on Mac OS X only.

(One variant only)

Relevance bar

A control that indicates a level of relevance. Available on Mac OS X only.

(One variant only)

Round button

Similar to a push button, except that it is round. Available on Mac OS X only.

Normal size.
Large size.

Definition of the Term "Controls"

On Mac OS 8/9, prior to the introduction of Mac OS 8 and the Appearance Manager, a control was defined as an "on-screen object 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 Mac OS 8/9 theme-compliance introduced with the Appearance Manager. For example, using the provided separator line "control" to draw separator lines will ensure that those lines are drawn with the correct Platinum appearance (and, on Mac OS X, the correct Aqua "look") in both the activated and deactivated modes.

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 feature of some of the controls introduced with Mac OS 8 and the Appearance Manager.)

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 that 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 Figs 1 and 2.

The Control Definition Function

Control definition functions (CDEFs), which are stored as resources of type 'CDEF', determine the appearance and behaviour of a control.

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.

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

Note that the a single 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 alerts and dialogs.

In windows and dialogs containing 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. On Mac OS 8/9, the default push button is outlined. On Mac OS X it is coloured and pulsing. (See Fig 1.)

In your application, pressing the Enter and Return keys should result in the same action as clicking on the the default push button.

Checkboxes

Checkboxes are typically used in dialogs. Checkboxes provide alternative choices and act like toggle switches. Each checkbox must have a title, which should reflect two clearly opposite states.

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 that 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.

Auto-Toggling Variant

When the auto-toggling variant is being used, checkboxes 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 checkbox's new state. There is no need to programmatically change the control's value after tracking successfully.

Radio Buttons

Like checkboxes, radio buttons are typically used in dialogs. Unlike checkboxes, radio buttons within a group are mutually exclusive.

Radio buttons are typically grouped. Each group must have a label indicating the kind of choices offered by the group, and each button must have a title indicating what it does.

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 that 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.

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.

Scroll Bars

Scroll bars scroll a document within a window. Scroll bars have scroll arrows at each end and a movable scroll box (Mac OS 8/9) or scroller (Mac OS X). The part of a scroll bar not occupied by the scroll arrows and scroll box/scroller is called the gray area (Mac OS 8/9) or track (Mac OS X). When the user clicks in a scroll arrow or gray area/track, or drags the scroll box/scroller, your application must scroll the document as appropriate.

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/scroller, the scroll box/scroller moves and the document scrolls as the user moves the mouse. (Without live scrolling, only a ghosted image of the scroll box/scroller moves. In addition, the document is only scrolled, and the scroll box/scroller proper is only redrawn at its new location, when the user releases the mouse button.)

Scroll Arrows and Gray Area/Track

When the scroll arrows are clicked, your application should move the scroll box/scroller 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 specified direction. (In a text document, one unit would typically be one line of text.)

When the gray area/track is clicked above the scroll box/scroller, your application should move the document down so that the top unit of the previous view is at the bottom of the new view, and it should move the scroll box/scroller accordingly. A similar, but upward movement, should occur when the user clicks in the gray area/track below the scroll box/scroller.

Scroll Box/Scroller

Live Feedback Variant Not Used

When the live feedback variant is not being used, and when the user drags the scroll box/scroller, the Control Manager redraws the scroll box/scroller 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 scroll box/scroller 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/scroller, the Control Manager continually redraws the scroll box/scroller, and continually returns the control's position (that is, its value) as the scroll box/scroller moves. Once again, your application uses this value to display the appropriate portion of the document.

Proportional Scroll Boxes/Scrollers

A proportional scroll box/scroller 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.

Those of your application's scroll boxes/scrollers created from 'CNTL' resources 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. (On Mac OS 8/9, the user must also have selected Smart Scrolling on in the Options tab in the Appearance control panel.) For scroll bars created programmatically using the function CreateScrollBarControl, you pass the size of the view area in the viewSize parameter.

The following functions are relevant to proportional scroll boxes/scrollers:

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 an alternative method of providing the user with a list of choices. The items in a pop-up menu button's menu should be mutually exclusive. Pop-up menus should be used to provide a choice of attributes, and should not be used to provide additional commands.

Primary Group Boxes (Text Title Variant)

A primary group box (text title variant) is a control that consists of a rectangular 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 (callback) functions, known as user pane functions, which perform actions such as drawing, hit testing, etc.

Activating, Deactivating, Hiding, Showing, Enabling, and Disabling Controls

Activating and Deactivating Controls

A control can be either active or inactive. A control should be made inactive when it is inappropriate for your application to respond to a mouse-down event in that control. The Control Manager displays inactive controls in a dimmed state. The Control Manager displays inactive basic controls and inactive primary group boxes as shown at Figs 3 and 4.

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. (But see also Enabling and Disabling Controls, below.)

  • 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.

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.

Enabling and Disabling Controls

EnableControl and DisableControl may be used to enable and disable controls. IsControlEnabled may be used to determine whether a control is enabled or disabled.

A distinction needs to be made between an disabled control and a deactivated control. A deactivated control is simply a control in a deactivated window. (All controls in a window should be deactivated when the window is deactivated.) A disabled control, on the other hand, is a control which the user should not currently be able to manipulate. The activation state of the window is immaterial in this case.

A "delete" button, for example, should be disabled when nothing is currently selected. As another example, controls in floating windows should never be deactivated, simply because floating windows themselves should never be deactivated. However, a control in a floating window should be disabled if the user should not currently be able to manipulate it.

It follows that a control in a deactivated window must be deactivated and may be either disabled or enabled.

A problem here is that, as of the time of writing, EnableControl, DisableControl, and IsControlEnabled are only available on Mac OS X. Thus, on Mac OS 8/9, the only way to deny user access to a control in an active window is to deactivate it.

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.

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 newer 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

As previously stated, controls (or, more usually, a group of controls) may be embedded in embedder controls.

The Root Control

The embedding of controls in a window requires that the window have a root control. 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.

On Mac OS X, a root control is created automatically in all document windows that have at least one other control. On Mac OS 8/9, however, you must explicitly create the root control in document windows 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 5. 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 5, 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 5, 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 5 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

Getting and setting control data is essentially 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 reference 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

Causes a push button to be drawn with the appearance of the default push button, or returns whether the push button is drawn with the default push button appearance.

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.

kControlPopupButtonMenuRefTag

Gets or sets the menu reference for a pop-up menu.

Data type returned or set: MenuRef

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

kControlScrollBarShowsArrowsTag

Specifies whether the scroll arrows are to be drawn or not.

Data type set: Boolean

The Control Object

The Control Manager stores information about individual controls in opaque data structures called control objects. The data type ControlRef is defined as a pointer to a control object:

     typedef struct OpaqueControlRef*  ControlRef;

Accessor Functions

Accessor functions are provided to access the information in control objects. The accessor functions are as follows:

Function

Description

GetControlOwner
SetControlOwner

Gets a reference to the window in which the specified control is located.
Assigns the specified control to a specified window.

GetControlBounds
SetControlBounds

Sets the specified control's enclosing rectangle.
Gets the specified control's enclosing rectangle.

IsControlVisible
SetControlVisibility

Determines if the specified control is currently hidden or showing.
Shows or hides the specified control.

IsControlHilited
HiliteControl
GetControlHilite

Determines if the specified control is currently highlighted.
Changes active/inactive status of a control or highlights a specified part of a control.
Determines whether the specified control is currently highlighted.

GetControlValue
SetControlValue

Gets the specified control's value (16 bit) as set by SetControlValue.
Sets the specified control's value (16 bit).

GetControl32BitValue
SetControl32BitValue

Sets the specified control's value as set by SetControl32BitValue.
Gets the specified control's value.

GetControlMaximum
SetControlMaximum

Gets the specified control's maximum value (16 bit) as set by SetControlMaximum.
Sets the specified control's maximum value (16 bit).

GetControl32BitMaximum
SetControl32BitMaximum

Gets the specified control's maximum value as set by SetControl32BitMaximum.
Sets the specified control's maximum value.

GetControlMinimum
SetControlMinimum

Gets the specified control's minimum value (16 bit) as set by SetControlMinimum.
Sets the specified control's minimum value (16 bit).

GetControl32BitMinimum
SetControl32BitMinimum

Gets the specified control's minimum value as set by SetControl32BitMinimum.
Sets the specified control's minimum value.

GetControlDataHandle
SetControlDataHandle

Gets a handle to data specific to a particular control type.
Sets a handle to data specific to a particular control type.

GetControlAction
SetControlAction

Gets the universal procedure pointer to the specified control's action function.
Sets a universal procedure pointer to the specified control's action function.

GetControlReference
SetControlReference

Gets the specified control's reference constant.
Sets the specified control's reference constant.

GetControlTitle
SetControlTitle

Gets the specified control's title.
Set the specified control's title.

GetControlDefinition

Gets the specified control's definition function.

GetControlPopupMenuHandle
SetControlPopupMenuHandle

Gets the specified popup menu button control's menu reference.
Sets the menu reference for a popup menu button control.

GetControlPopupMenuID
SetControlPopupMenuID

Gets the specified pop-up menu button control's menu ID.
Sets the menu ID for a pop-up menu button control.

Creating Controls

When you use the Dialog Manager to implement push buttons, radio buttons, checkboxes or pop-up menu buttons in alerts or dialogs, Dialog Manager functions automatically use Control Manager functions to create the controls for you.

For document and utility windows, you can create controls from 'CNTL' resources or you can create them programmatically.

Creating Controls From 'CNTL' Resources

You create controls from 'CNTL' resources using GetNewControl. GetNewControl, which takes a 'CNTL' resource ID and a reference to the window object, creates a control object from the information in the resource, adds the control object to the control list for your window, and returns a reference to the control.

Before you can create a control using GetNewControl, you must, of course, first create the necessary 'CNTL' resource. 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 6 shows the structure of a compiled 'CNTL' resource and how it "feeds" the control object.

The following describes the main fields of the 'CNTL' resource:

Field

Description

INITIAL RECTANGLE

A rectangle that determines the control's size and location. It is specified in local coordinates.

INITIAL VALUE

Initial value for the control. (See Values for Controls, below).

VISIBILITY

Visibility of the control. When this field contains the value true, GetNewControl draws the control immediately. When this field contains false, the application must use ShowControl when the time has come to display the control.

MAXIMUM VALUE

Maximum value of the control. (See Values for Controls, below).

MINIMUM VALUE

Minimum value for the control. (See Values for Controls, below).

CONTROL DEFINITION ID

The control definition ID. (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. The value must be between -32768 and 32767.

Whatever maximum value is appropriate. The value must be between -32768 and 32767.

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. These fields are thus said to be "overloaded".

Creating 'CNTL' Resources Using Resorcerer

Fig 7 shows a 'CNTL' resource being created with Resorcerer.

Creating Controls Programmatically

You can also create controls programmatically. The following functions, which were introduced with Carbon, may be used to programmatically create the controls described in this chapter:

Function

Parameters

CreatePushButtonControl

Rectangle, title (Pascal string).

CreatePushButtonWithIconControl

Rectangle, title, address of ControlButtonContentInfo structure, icon alignment.

CreateRadioButtonControl

Rectangle, title, auto-toggle/non-auto-toggle.

CreateCheckBoxControl

Rectangle, title, autotoggle/non-autotoggle.

CreateScrollBarControl

Rectangle, control value, minimum value,maximum value, size of view area, live-feedback/non-live-feedback, UPP to control action function.

CreatePopupButtonControl

Rectangle, title, menu ID,variable-width/non-variable-width, title width,title justification, title style.

CreateGroupBoxControl

Rectangle, title, primary/secondary.

CreateUserPaneControl

Rectangle, features.

Push Button Content and Icon Alignment

One of the parameters in calls to CreateScrollBarControl is the address of a structure of type ControlButtonContentInfo:

     struct ControlButtonContentInfo
     {
       ControlContentType contentType;
       union 
       {
         SInt16      resID;
         CIconHandle cIconHandle;
         Handle      iconSuite;
         IconRef     iconRef;
         PicHandle   picture;
         Handle      ICONHandle;
       }             u;
     };
     typedef struct ControlButtonContentInfo ControlButtonContentInfo;

If, for example, you wish to specify a colour icon for the button's icon content, you would assign kControlContentCIconRes to the contentType field and the icon's resource ID to the resID field.

Another parameter in calls to CreatePushButtonWithIconControl is a value of type ControlPushButtonIconAlignment. Relevant constants are:

     kControlPushButtonIconOnLeft
     kControlPushButtonIconOnRight

Additional Considerations - Scroll Bars

When creating scroll bars, you typically call GetNewControl or CreateScrollBarControl immediately after you create the window and 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.)

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.

A scroll bar for a document window is, by convention, 16 pixels wide (vertical scroll bars) and 16 pixels high (horizontal scroll bars). The Control Manager draws one-pixel lines around the scroll bar, based on the rectangle enclosing the scroll bar. As shown at Fig 8, these outside lines should overlap the inside lines of the window frame.

The following calculations determine the rectangle for a vertical scroll bar for a document window:

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.

Do not include the title bar area in these calculations.

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.

When the user resizes the window, the initial maximum settings and location, as specified in the 'CNTL' resource or CreateScrollBarControl call, must therefore be changed dynamically by the application as required. Typically, this is achieved by storing handles to each scroll bar in a document structure associated with the window and then using Control Manager functions to change control settings.

Additional Considerations - 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

Pop-up Menu Button Title Width

Fig 9 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 9). 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 the control is created, the first menu item and the number of items in the pop-up menu button are stored in the control object. When the user chooses a different menu item, the Control Manager changes the item number value stored in the control object 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 control reference constant value in the control object 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. In this situation, you can still store a reference constant in the control object by calling SetControlReference after the control has been created.

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. 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

Specifies which fields of the structure should be applied to the control (see Control Font Style Flag Constants, below). If no flags are set, the control uses the system font (or, for control variants which use the window font, the window font).

font

The ID of the font family to use or, alternatively, a meta font constant (see Meta Font Constants, below).

size

If the kControlUseSizeMask is set in the flags field, specifies the point size of the text. If the kControlAddFontSizeMask bit is set in the flags field, specifies the size to add to the current point size of the text. Alternatively, a meta font constant may be assigned to this field (see Meta Font Constants, below).

style

Specifies the style to apply to the text. The bit numbers and the styles they represent are as follows. If all bits are clear, the plain font style is specified.

Bit Number

Style

0

Bold

1

Italic

2

Underline

3

Outline

4

Shadow

5

Condensed

6

Extended

mode

Specifies how characters are drawn in the bit image. (For a discussion of transfer modes, see Chapter 12.)

just

Specifies text justification. The relevant constants are as follows:

Constant

Value

teFlushDefault

0

teCenter

1

teFlushRight

2

teFlushLeft

3

foreColor

Specifies the RGB (red-green-blue) colour to use when drawing the text.

backColor

Specifies the RGB 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. 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.

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.

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.

Applies only to static text controls.

kControlUseBackColorMask 0x0010

The backColor field of the control font style structure is applied to the control.

Applies only 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.

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 -1

Use the system font.

kControlFontSmallSystemFont -2

Use the small system font.

kControlFontSmallBoldSystemFont -3

Use the small emphasised system font.

kControlFontViewSystemFont -4

Use the views font.

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.

Setting and Getting Control IDs

The following functions, which were introduced with Carbon, may be used to set and get a controlŐs ID, and to get a controlŐs kind:

Function

Description

SetControlID

Set a controlŐs ID.

GetControlID

Get a controlŐs ID.

GetControlByID

Get a reference to a control using the controlŐs ID.

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 Manager to implement push buttons, radio buttons, checkboxes or pop-up menu buttons in alerts or dialogs, Dialog Manager functions automatically use Control Manager functions to update the controls for you.

Moving Controls

You can change the position of a control using MoveControl, which erases the control, offsets the control's control rectangle, and redraws it at the specified new location

Removing Controls

DisposeControl may be used to remove a control from a window, delete it from the window's control list, and release the control object and associated data structures from memory. KillControls will dispose of all of a window's controls at once.

Handling Mouse Events in Controls

Overview

For mouse events in controls, you usually perform the following tasks:

  • Use FindWindow to determine the window in which the mouse-down event occurred.

  • If the mouse-down event occurred in the content region of the active window, use FindControl to determine whether the event occurred in a control and, if so, which control.

  • Call TrackControl or HandleControlClick to handle user interaction with the control as long as the user holds the mouse button down. The actionProc parameter passed to TrackControl, or the inAction parameter passed to HandleControlClick, should be as follows:

    • NULL for push buttons, checkboxes and radio buttons.

    • For scroll arrows and gray areas/tracks of scroll bars, a universal procedure pointer which invokes an application-defined action function which, in turn, causes the document to scroll as long as the user holds the mouse button down.

    • For the scroll box/scroller of scroll bars:

      • NULL if the non-live-feedback variant is being used.

      • If the live-feedback variant is being used, a pointer which invokes an application-defined action function which, in turn, causes the document to scroll while the scroll box is being dragged.

    • (ControlActionUPP) -1 for pop-up menu buttons. This causes TrackControl and HandleControlClick to use the action function defined within the pop-up CDEF, a pointer to which is stored in the control object.

    Note that, as an alternative to passing universal procedure pointers in the actionProc parameter of TrackControl, or the inAction parameter of HandleControlClick, you can preset the action function by passing the universal procedure pointer in the actionProc parameter of SetControlAction. (Ordinarily, you would call SetControlAction immediately after the control is created.) In this case, you must pass (ControlActionUPP) -1 in the actionProc and inAction parameters of TrackControl and HandleControlClick.

  • When TrackControl or HandleControlClick reports that the user has released the mouse button with the cursor in a control, respond appropriately, that is:

    • Perform the task identified by the push button title if the cursor is over a push button.

    • Toggle the value of the checkbox when the cursor is over a checkbox. (The Control Manager then redraws or removes the checkmark, as appropriate.)

    • Turn on the radio button, and turn off all other radio buttons in the group, when the cursor is over an active radio button.

    • Show more of the document in the direction of the scroll arrow when the cursor is over the scroll arrow or gray area/track of a scroll bar, and move the scroll box/scroller accordingly.

    • If the non-live-feedback scroll bar variant is being used, and when the cursor is over the scroll box/scroller, determine where the user has dragged the scroll box/scroller, and then display the corresponding portion of the document.

    • Use the new setting chosen by the user when the cursor is over a pop-up menu button.

Determining a Mouse-Down Event in a Control

FindControl will return both a reference to the control as well as a control part code when a mouse-down event occurs in a visible, active control. FindControl will set the control reference to NULL and return 0 as the control part code when a mouse-down occurs in an invisible or inactive control, or when the cursor is not in a control.

A control part code is an integer from 1 to 255. Part codes are assigned to a control by its CDEF. The CDEFs for the basic controls define the following part codes:

Constant

Value

Meaning

kControlNoPart 0

Event did not occur in any control.

Also unhighlights any highlighted part of the control when passed to the HiliteControl function.

kControlLabelPart 1

Event occurred in the label of a pop-up menu button.

kControlMenuPart 2

Event occurred in the menu of a pop-up menu button.

kControlButtonPart 10

Event occurred in a push button.

kControlCheckBoxPart 11

Event occurred in a checkbox.

kControlRadioButtonPart 12

Event occurred in a radio button.

kControlUpButtonPart 20

Event occurred in the up (or left )scroll arrow of a scroll bar.

kControlDownButtonPart 21

Event occurred in the down (or right) button of a scroll bar.

kControlPageUpPart 22

Event occurred in the page-up part of a scroll bar.

kControlPageDownPart 23

Event occurred in the page-down part of a scroll bar.

kControlIndicatorPart 129

Event occurred in the scroll box of a scroll bar.

A newer function (FindControlUnderMouse) will return a reference to the control even if no part was hit and can determine whether a mouse-down event has occurred even if the control is deactivated, whereas FindControl will not.

Tracking the Cursor in a Control

When the call to FindControl determines that the cursor was in a control when the user pressed the mouse button, you should call TrackControl or HandleControlClick to follow and respond to the user's movements.

You can use an action function to perform additional actions while the user holds the mouse button down. Typically, action functions are used to continuously scroll the window's contents while the cursor is on a scroll arrow or gray area/track of a scroll bar, or in the scroll box/scroller of a live-feedback scroll bar. (As previously stated, you pass a pointer to this action function in the actionProc parameter of TrackControl or the inAction parameter of HandleControlClick).

TrackControl and HandleControlClick return the control's control part code if the user releases the mouse button while the cursor is still inside the control part, or kControlNoPart (0) if the cursor is outside the control part when the button is released. Your application should then respond appropriately.

Determining and Changing Control Settings, and Getting a Control's Kind

Determining and Changing Control Settings

Your application often needs to determine the current setting and other values of a control when the user clicks the control. When the user clicks a non-auto-toggling checkbox, for example, your application must determine whether the box is currently checked before deciding whether to clear or draw the checkmark.

Your application can use the control value accessor functions described at The Control Object, above, to get and set a control's value, minimum value, and maximum value.

Getting a Control's Kind

You can determine a control's kind using GetControlKind. The control's kind is returned in a structure of type ControlKind:

     struct ControlKind
     {
       OSType signature;  // kControlKindSignatureApple ('appl') for all system controls
       OSType kind;
     };
     typedef struct ControlKind ControlKind;

For the controls addressed in this chapter, the following constants pertain to the kind field:

Constant

Value

Control Kind

kControlKindPushButton 'push'

Push button.

kControlKindPushIconButton 'picn'

Push button (colour icon variant).

kControlKindCheckBox 'cbox'

Checkbox.

kControlKindRadioButton 'rdio'

Radio button.

kControlKindScrollBar 'sbar'

Scroll bar.

kControlKindPopupButton 'popb'

Pop-up menu button.

kControlKindGroupBox 'grpb'

Primary group box (text title variant).

kControlKindUserPane 'upan'

User pane.

An alternative method is to call GetControlData with kControlKindTag passed in the inTagName parameter and the address of a variable of type ControlKind passed in the inBuffer parameter.

A problem here is that, as of the time of writing, both GetControlKind and the alternative method were only available on Mac OS X.

Moving and Resizing Scroll Bars

Your application must be able to size and move scroll bars dynamically in response to the user resizing your windows. The steps involved are:

  • Resize the window.

  • Make each scroll bar invisible using HideControl.

  • Move the scroll bars to the appropriate edges of the window using MoveControl.

  • Lengthen or shorten each scroll bar (as appropriate) using SizeControl.

  • After recalculating the maximum settings, update the settings and redraw the scroll boxes using SetControlMaximum and SetControlValue.

  • Make each scroll bar visible at its new location using ShowControl.

Each of the functions involved require a referece to the relevant scroll bar control. When your application creates a window, it should store references for each scroll bar in a document structure associated with that window.

Scrolling Operations With Scroll Bars

Scrolling Basics

Relationship Between Document, Window, and Scroll Bar

The relationship between a document and a window, and their representation in a scroll bar, is shown at Fig 10.

Distance and Direction to Scroll

When the user scrolls a document using scroll bars, your application must first determine the distance and direction to scroll. The distance to scroll is as follows:

  • When the user drags the scroll box to a new location, your application should scroll the document a corresponding distance.

  • For a click on a scroll arrow, you should scroll by a distance appropriate to your application. For example, a text editing application might scroll one line of text for one click in the vertical scroll bar.

  • For a click in the gray area, you should scroll by a distance appropriate to your application. For example, a text editing application should ordinarily scroll by a distance equal to the height of the window less one text line.

Direction to scroll is determined by whether the scrolling distance is expressed as a positive or negative number. The scrolling distance will be expressed as a negative number if the user scrolls down from the beginning of the document, and as a positive number if the user scrolls up towards the beginning of the document.

Scrolling the Pixels

With the distance and direction to scroll determined, the next step is to scroll the pixels displayed in the window by that distance and in that direction. Typically, ScrollRect is used for that purpose.

Moving the Scroll Box/Scroller

If the user did not effect the scroll using the scroll box/scroller, the scroll box/scroller must then be repositioned using SetControlValue.

Updating the Window

The final step is to either call a function which generates an update event or directly call your application's update function. Your application's update function should call UpdateControls (to update the scroll bars) and redraw the appropriate part of the document in the window.

Scrolling Example

Half the complexity of scrolling lays in ensuring that that part of the document which is displayed in the window correlates with the scroll bar control value, and vice versa, at all times.

Consider the left-top of Fig 11. This newly opened document consists of 35 lines of monostyled text with a line height of 10 pixels. The document is, therefore, 350 pixels long. The upper-left point of the document is identical to the window origin, that is, both are at (0,0).

The window height is 150 pixels (15 lines of text). Thus the maximum setting for the scroll bar is equivalent to 200 pixels down in the document. (As shown at Fig 10, a vertical scroll bar's maximum setting equates to the length of the document minus the height of the window.)

Now assume that the user drags the scroll box down the vertical scroll bar. This means that your application must move the text up by the appropriate amount. Moving a document up means a negative scrolling value.

Suppose the application, using GetControlValue, determines that the scroll bar's control value is 100. The application must then call ScrollRect to shift the bits displayed in the window by a distance of -100 pixels (that is, 10 lines of text). As shown at the top-right of Fig 11, five lines from the bottom of the previous window display now appear at the top of the window.

Note that, in all this, ScrollRect does not change the coordinate system of the window; it simply moves the bits in the window to new coordinates that are still in the window's local coordinate system. In terms of the window's local coordinate system, then, the upper left corner of the document is now at (-100,0).

To facilitate updating of the window (see the update region at Fig 11), SetOrigin must now be used to change the local coordinate system of the window so that the application can treat the upper left corner of the document as again lying at (0,0). This restoration of the document's original coordinate space makes it easier for the application to determine which lines of the document to draw in the update region of the window. (See bottom-left of Fig 11.)

The application now updates the window by drawing lines 16 to 24, which it stores in its document structure as beginning at (160,0) and ending at (250,0).

Finally, because the Window and Control Managers always assume that the window's upper-left point is at (0,0) when they draw in the window, the window origin cannot be left at (100,0). Accordingly, the application must use SetOrigin to reset it to (0,0) after performing its own drawing, (See bottom-right of Fig 11.)

To summarise:

  • The user dragged the scroll box about half way down the vertical scroll bar. The application determined that the distance and direction to scroll was -100 pixels.

  • The application passed this distance to ScrollRect, which shifted the bits in the window 100 pixels upwards and created an update region in the vacated area of the window.

  • The application passed the vertical scroll bar's current setting (100) in a parameter to SetOrigin so that the document's local coordinates were used when the update region of the window was redrawn. This changed the window's origin to (100,0).

  • The application drew the text in the update region.

  • The application reset the window's origin to (0,0).

Alternative to SetOrigin

There are alternatives to the SetOrigin methodology. SetOrigin simply helps you to offset the window's origin by the scroll bar's current settings when you update the window so that you can locate objects in a document using a coordinate system where the upper-left corner of the document is always at (0,0).

As an alternative to this approach, your application can leave the upper-left corner of the window at (0,0) and instead offset the items in your document, using OffsetRect, by an amount equal to the scroll bar's settings.

Scrolling a TextEdit Document and Scrolling Using the List Manager

TextEdit is a collection of functions and data structures which you can use to provide your application with basic text editing capabilities. Chapter 21 addresses, amongst other things, the scrolling of TextEdit documents.

For scrolling lists of graphic or textual information, your application can use the List Manager to implement scroll bars. (See Chapter 22.)

Small Versions of Controls

Human Interface Guidelines permit the use of small versions of certain controls, which should only be used when space is at a premium. Full size and small controls should not be mixed in the same window.

The following lists those controls described in this chapter that are available in small versions, and describes how to create them.

Control

Mac OS X

Mac OS 8/9

Push button

Make the control's rectangle 17 pixels high and call SetControlFontStyle to set the small system font.

Make the control's rectangle 17 pixels high and use SetControlFontStyle to set the small system font.

Radio button
Checkbox

Call SetControlData with the kControlSizeTag tag to make the control proper small, and call SetControlFontStyle to set the title to the small system font.

(Not available.)

Pop-up menu button

Create the control from a 'CNTL' resource, specifying the kControlPopupUseWFontVariant, and set the owner window's font to the small system font.

Create the control from a 'CNTL' resource, specifying the kControlPopupUseWFontVariant, and set the owner window's font to the small system font.

Scroll bar

Call SetControlData with the kControlSizeTag tag.

Make the control's rectangle 11 pixels wide (vertical scroll bars) or high (horizontal scroll bars.

Small scroll bars should only be used in floating windows. Fig 12 shows an example.

Main Control Manager Constants, Data Types and Functions Relevant to the Basic Controls, Primary Group Box & User Panes

Constants

Control Definition IDs

kControlPushButtonProc             = 368
kControlPushButLeftIconProc        = 374
kControlPushButRightIconProc       = 375
kControlCheckBoxProc               = 369
kControlCheckBoxAutoToggleProc     = 371
kControlRadioButtonProc            = 370
kControlRadioButtonAutoToggleProc  = 372
kControlScrollBarProc              = 384
kControlScrollBarLiveProc          = 386
kControlPopupButtonProc            = 400
kControlGroupBoxTextTitleProc      = 160
kControlUserPaneProc               = 256

Push Button Icon Alignment

kControlPushButtonIconOnLeft   = 6
kControlPushButtonIconOnRight  = 7

Pop-up Menu Button Variants

kControlPopupFixedWidthVariant     = 1 << 0
kControlPopupVariableWidthVariant  = 1 << 1
kControlPopupUseAddResMenuVariant  = 1 << 2
kControlPopupUseWFontVariant       = 1 << 3

Pop-up Title Characteristics

popupTitleBold        = 1 << 8
popupTitleItalic      = 1 << 9
popupTitleUnderline   = 1 << 10
popupTitleOutline     = 1 << 11
popupTitleShadow      = 1 << 12
popupTitleCondense    = 1 << 13
popupTitleExtend      = 1 << 14
popupTitleNoStyle     = 1 << 15

Control Variants

kControlNoVariant                     = 0
kControlUsesOwningWindowsFontVariant  = 1 << 3

Control Part Codes

kControlNoPart           = 0
kControlEntireControl    = 0
kControlLabelPart        = 1
kControlMenuPart         = 2
kControlCheckBoxPart     = 11
kControlRadioButtonPart  = 11
kControlUpButtonPart     = 20
kControlDownButtonPart   = 21
kControlPageUpPart       = 22
kControlPageDownPart     = 23
kControlIndicatorPart    = 129
kControlDisabledPart     = 254
kControlInactivePart     = 255

Checkbox Value Constants

kControlCheckBoxUncheckedValue  = 0
kControlCheckBoxCheckedValue    = 1
kControlCheckBoxMixedValue      = 2

Radio Button Value Constants

kControlRadioButtonUncheckedValue  = 0
kControlRadioButtonCheckedValue    = 1
kControlRadioButtonMixedValue      = 2

Control Data Tag Constants

kControlPushButtonDefaultTag       = FOUR_CHAR_CODE('dflt')
kControlPushButtonCancelTag        = FOUR_CHAR_CODE('cncl')
kControlPopupButtonMenuRefTag      = FOUR_CHAR_CODE('mhan')
kControlPopupButtonMenuIDTag       = FOUR_CHAR_CODE('mnid')
kControlPopupButtonExtraHeightTag  = FOUR_CHAR_CODE('exht')
kControlGroupBoxTitleRectTag       = FOUR_CHAR_CODE('trec')

Control Data Tag Constants (Mac OS X)

kControlKindTag                    = FOUR_CHAR_CODE('kind')
kControlSizeTag = FOUR_CHAR_CODE('size')

Control Font Style Flag Constants

kControlUseFontMask        = 0x0001
kControlUseFaceMask        = 0x0002
kControlUseSizeMask        = 0x0004
kControlUseForeColorMask   = 0x0008
kControlUseBackColorMask   = 0x0010
kControlUseModeMask        = 0x0020
kControlUseJustMask        = 0x0040
kControlUseAllMask         = 0x00FF
kControlAddFontSizeMask    = 0x0100

Meta Font Constants

kControlFontBigSystemFont        = -1
kControlFontSmallSystemFont      = -2
kControlFontSmallBoldSystemFont  = -3
kControlFontViewSystemFont       = -4

Push Button Icon Alignment

kControlPushButtonIconOnLeft     = 6
kControlPushButtonIconOnRight    = 7

Control Image Content

kControlContentIconSuiteRes      = 1
kControlContentCIconRes          = 2
kControlContentICONRes           = 4
kControlContentIconSuiteHandle   = 129
kControlContentCIconHandle       = 130
kControlContentPictHandle        = 131
kControlContentIconRef           = 132
kControlContentICON              = 133

Control Kind

kControlKindPushButton            = 'push'
kControlKindPushIconButton        = 'picn'
kControlKindCheckBox              = 'cbox'
kControlKindRadioButton           = 'rdio'
kControlKindScrollBar             = 'sbar'
kControlKindPopupButton           = 'popb'
kControlKindGroupBox              = 'grpb'
kControlKindUserPane              = 'upan'

Data Types

typedef struct OpaqueControlRef*  ControlRef;
typedef ControlRef  ControlHandle;
typedef SInt16      ControlPartCode;
typedef SInt16 ControlContentType; typedef UInt16 ControlPushButtonIconAlignment;

Control Button Content Info

struct ControlButtonContentInfo 
{
  ControlContentType  contentType;
  union 
  {
    SInt16      resID;
    CIconHandle cIconHandle;
    Handle      iconSuite;
    IconRef     iconRef;
    PicHandle   picture;
    Handle      ICONHandle;
  } u;
};
typedef struct ControlButtonContentInfo ControlButtonContentInfo;
typedef ControlButtonContentInfo *ControlButtonContentInfoPtr;

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;

ControlID

struct ControlID
{
  OSType signature;
  SInt32 id;
};
typedef struct ControlIDControlID;

ControlKind

struct ControlKind
{
  OSType signature;
  OSType kind;
};
typedef struct ControlKind ControlKind;

Functions

Creating Controls

ControlRef  GetNewControl(SInt16 controlID,WindowPtr owner);
ControlRef  NewControl(WindowPtr owningWindow,const Rect *boundsRect,ConstStr255Param
            title,Boolean initiallyVisible,SInt16 initialValue,SInt16 minimumValue,
            SInt16 maximumValue,SInt16 procID,SInt32 controlReference);
OSStatus    CreatePushButtonControl(WindowRef window,const Rect *boundsRect,
            ConstStr255Param title,ControlRef *outControl);
OSStatus    CreatePushButtonWithIconControl(WindowRef window,const Rect *boundsRect,
            ConstStr255Param title,ControlButtonContentInfo *icon,
            ControlPushButtonIconAlignment iconAlignment,ControlRef *outControl);
OSStatus    CreateRadioButtonControl(WindowRef window, const Rect *boundsRect,
            ConstStr255Param title,Boolean autoToggle,ControlRef *outControl);
OSStatus    CreateCheckBoxControl(WindowRef window,const Rect *boundsRect,
            ConstStr255Param title,Boolean autoToggle,ControlRef *outControl);
OSStatus    CreateScrollBarControl(WindowRef window,Rect *boundsRect,
            SInt32 value,SInt32 minimum,SInt32 maximum,SInt32 viewSize,
            Boolean liveTracking,ControlActionUPP liveTrackingProc,
            ControlRef *outControl);
OSStatus    CreatePopupButtonControl(WindowRef window,const Rect *boundsRect,
            ConstStr255Param title,SInt16 menuID,Boolean variableWidth,
            SInt16 titleWidth,SInt16 titleJustification,Style titleStyle,
            ControlRef *outControl);
OSStatus    CreateGroupBoxControl(WindowRef window,const Rect *boundsRect,
            ConstStr255Param title,Boolean primary,ControlRef *outControl);
OSStatus    CreateUserPaneControl(WindowRef window,const Rect *boundsRect,
            UInt32 features,ControlRef *outControl);

Removing Controls

void  DisposeControl(ControlRef theControl);
void  KillControls(WindowPtr theWindow);

Embedding Controls

OSErr  CreateRootControl(WindowPtr inWindow,ControlRef *outControl);
OSErr  GetRootControl(WindowPtr inWindow,ControlRef *outControl);
OSErr  EmbedControl(ControlRef inControl,ControlRef inContainer);
OSErr  AutoEmbedControl(ControlRef inControl,WindowPtr inWindow);
OSErr  CountSubControl(ControlRef inControl,SInt16 *outNumChildren);
OSErr  GetIndexedSubControl(ControlRef inControl,SInt16 inIndex,
       ControlRef *outSubControl);
OSErr  GetSuperControl(ControlRef inControl,ControlRef *outParent);
OSErr  SetControlSupervisor(ControlRef inControl,ControlRef inBoss);
OSErr  DumpControlHierarchy(WindowPtr inWindow,const FSSpec *inDumpFile);

Displaying and Manipulating Controls

void     MoveControl(ControlRef theControl,SInt16 h,SInt16 v);
void     SizeControl(ControlRef theControl,SInt16 w,SInt16 h);
void     UpdateControls(WindowPtr theWindow,RgnHandle updateRgn);
void     DrawControls(WindowPtr theWindow);
void     DrawOneControl(ControlRef theControl);
void     DrawControlInCurrentPort(ControlRef inControl);
Boolean  IsControlActive (ControlRef inControl);
OSErr    ActivateControl (ControlRef inControl);
OSErr    DeactivateControl(ControlRef inControl);
Boolean  IsControlVisible(ControlRef inControl);
void     HideControl(ControlRef theControl);
void     ShowControl(ControlRef theControl);
OSErr    SetControlVisibility (ControlRef inControl,Boolean inIsVisible,
         Boolean inDoDraw);
OSErr    SendControlMessage(ControlRef inControl,SInt16 inMessage,SInt32 inParam);
void     DragControl(ControlRef theControl,Point startPt,const Rect *limitRect,
         const Rect *slopRect,DragConstraint axis);
Boolean  IsControlHilited(ControlRef control);
void     HiliteControl(ControlRef theControl,ControlPartCode hiliteState);

Enabling and Disabling Controls (Mac OS X Only)

OSStatus    EnableControl(ControlRef inControl);
OSStatus    DisableControl(ControlRef inControl);
Boolean     IsControlEnabled(ControlRef inControl);

Handling Events in Controls

ControlPartCode  FindControl(Point thePoint,WindowPtr theWindow,
                 ControlRef *theControl);
ControlRef       FindControlUnderMouse(Point inWhere,WindowPtr inWindow,
                 SInt16 *outPart);
ControlPartCode  TrackControl(ControlRef theControl,Point thePoint,
                 ControlActionUPP actionProc);
Sint16           HandleControlClick(ControlRef inControl,Point inWhere,
                 SInt16 inModifiers,  ControlActionUPP nAction);
ControlPartCode  TestControl(ControlRef theControl, PointthePt);

Accessing and Changing Control Settings and Data

WindowPtr   GetControlOwner(ControlRef control);
void        SetControlOwner(ControlRef control,WindowPtr owner);
Rect *      GetControlBounds(ControlRef control,Rect *bounds);
void        SetControlBounds(ControlRef control,const Rect *bounds);
Boolean     IsControlHilited(ControlRef control);
UInt16      GetControlHilite(ControlRef control);
Handle      GetControlDefinition(ControlRef control);
Handle      GetControlDataHandle(ControlRef control);
void        SetControlDataHandle(ControlRef control,Handle dataHandle);
MenuHandle  GetControlPopupMenuHandle(ControlRef control);
void        SetControlPopupMenuHandle(ControlRef control,MenuHandle popupMenu);
short       GetControlPopupMenuID(ControlRef control);
void        SetControlPopupMenuID(ControlRef control,short   menuID);
SInt16      GetControlValue(ControlRef theControl);
void        SetControlValue(ControlRef theControl,SInt16 theValue);
SInt16      GetControlMinimum(ControlRef theControl);
void        SetControlMinimum(ControlRef theControl,SInt16 newMinimum);
SInt16      GetControlMaximum(ControlRef theControl);
void        SetControlMaximum(ControlRef theControl,SInt16 newMaximum);
SInt32      GetControl32BitValue(ControlRef theControl);
void        SetControl32BitValue(ControlRef theControl,SInt32 newValue);
SInt32      GetControl32BitMaximum(ControlRef theControl);
Void        SetControl32BitMaximum(ControlRef theControl,SInt32 newMaximum);
SInt32      GetControl32BitMinimum(ControlRef theControl);
Void        SetControl32BitMinimum(ControlRef theControl,SInt32 newMinimum);
void        GetControlTitle(ControlRef theControl,Str255 title);
void        SetControlTitle(ControlRef theControl,ConstStr255Param title);
OSStatus    SetControlTitleWithCFString(ControlRef inControl,CFStringRef inString);
SInt32      GetControlReference(ControlRef theControl);
void        SetControlReference(ControlRef theControl,SInt32 data);
ControlActionUPP  GetControlAction(ControlRef theControl);
void        SetControlAction(ControlRef theControl,ControlActionUPP actionProc);
SInt32      GetControlViewSize(ControlRef theControl);
Void        SetControlViewSize(ControlRef theControl,SInt32 newViewSize);
SInt16      GetControlVariant(ControlRef theControl);
OSErr       SetControlData(ControlRef inControl,ControlPartCode inPart,
            ResType inTagName,Size inSize,Ptr inData);
OSErr       GetControlData (ControlRef inControl,ControlPartCode inPart,
            ResType inTagName,Size inBufferSize,Ptr inBuffer,Size *outActualSize);
OSErr       GetControlDataSize(ControlRef inControl,ControlPartCode inPart,
            ResType inTagName,Size *outMaxSize);
OSErr       SetControlVisibility(ControlRef inControl,Boolean inIsVisible,
            Boolean inDoDraw);

Setting the Control Font Style

OSErr  SetControlFontStyle  (ControlRef inControl,const ControlFontStyleRec *inStyle)

Setting and Getting Control IDs

OSStatus    SetControlID(ControlRef inControl,const ControlID *inID);
OSStatus    GetControlID(ControlRef inControl,ControlID *outID);
OSStatus    GetControlByID(WindowRef inWindow,const ControlID *inID,ControlRef *outControl);

Getting Control Kind (Mac OS X)

OSStatus    GetControlKind(ControlRef inControl,ControlKind *outControlKind);

Creating and Disposing of Universal Procedure Pointers for Control Action Functions

ControlActionUPP  NewControlActionUPP(ControlActionProcPtr userRoutine);
void              DisposeControlActionUPP(ControlActionUPP userUPP);

Application-Defined (Callback) Function

void        myControlActionFunction(ControlRef theControl,ControlPartCode partCode);

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Go from lowly lizard to wicked Wyvern in...
Do you like questing, and do you like dragons? If not then boy is this not the announcement for you, as Loongcheer Game has unveiled Quest Dragon: Idle Mobile Game. Yes, it is amazing Square Enix hasn’t sued them for copyright infringement, but... | Read more »
Aether Gazer unveils Chapter 16 of its m...
After a bit of maintenance, Aether Gazer has released Chapter 16 of its main storyline, titled Night Parade of the Beasts. This big update brings a new character, a special outfit, some special limited-time events, and, of course, an engaging... | Read more »
Challenge those pesky wyverns to a dance...
After recently having you do battle against your foes by wildly flailing Hello Kitty and friends at them, GungHo Online has whipped out another surprising collaboration for Puzzle & Dragons. It is now time to beat your opponents by cha-cha... | Read more »
Pack a magnifying glass and practice you...
Somehow it has already been a year since Torchlight: Infinite launched, and XD Games is celebrating by blending in what sounds like a truly fantastic new update. Fans of Cthulhu rejoice, as Whispering Mist brings some horror elements, and tests... | Read more »
Summon your guild and prepare for war in...
Netmarble is making some pretty big moves with their latest update for Seven Knights Idle Adventure, with a bunch of interesting additions. Two new heroes enter the battle, there are events and bosses abound, and perhaps most interesting, a huge... | Read more »
Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, don’t remind me I could currently buy him this month I’m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly “borrowed” many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »
Embark into the frozen tundra of certain...
Chucklefish, developers of hit action-adventure sandbox game Starbound and owner of one of the cutest logos in gaming, has released their roguelike deck-builder Wildfrost. Created alongside developers Gaziter and Deadpan Games, Wildfrost will... | Read more »

Price Scanner via MacPrices.net

Limited-time sale: 13-inch M3 MacBook Airs fo...
Amazon has the base 13″ M3 MacBook Air (8GB/256GB) in stock and on sale for a limited time for $989 shipped. That’s $110 off MSRP, and it’s the lowest price we’ve seen so far for an M3-powered... Read more
13-inch M2 MacBook Airs in stock today at App...
Apple has 13″ M2 MacBook Airs available for only $849 today in their Certified Refurbished store. These are the cheapest M2-powered MacBooks for sale at Apple. Apple’s one-year warranty is included,... Read more
New today at Apple: Series 9 Watches availabl...
Apple is now offering Certified Refurbished Apple Watch Series 9 models on their online store for up to $80 off MSRP, starting at $339. Each Watch includes Apple’s standard one-year warranty, a new... Read more
The latest Apple iPhone deals from wireless c...
We’ve updated our iPhone Price Tracker with the latest carrier deals on Apple’s iPhone 15 family of smartphones as well as previous models including the iPhone 14, 13, 12, 11, and SE. Use our price... Read more
Boost Mobile will sell you an iPhone 11 for $...
Boost Mobile, an MVNO using AT&T and T-Mobile’s networks, is offering an iPhone 11 for $149.99 when purchased with their $40 Unlimited service plan (12GB of premium data). No trade-in is required... Read more
Free iPhone 15 plus Unlimited service for $60...
Boost Infinite, part of MVNO Boost Mobile using AT&T and T-Mobile’s networks, is offering a free 128GB iPhone 15 for $60 per month including their Unlimited service plan (30GB of premium data).... Read more
$300 off any new iPhone with service at Red P...
Red Pocket Mobile has new Apple iPhones on sale for $300 off MSRP when you switch and open up a new line of service. Red Pocket Mobile is a nationwide MVNO using all the major wireless carrier... Read more
Clearance 13-inch M1 MacBook Airs available a...
Apple has clearance 13″ M1 MacBook Airs, Certified Refurbished, available for $759 for 8-Core CPU/7-Core GPU/256GB models and $929 for 8-Core CPU/8-Core GPU/512GB models. Apple’s one-year warranty is... Read more
Updated Apple MacBook Price Trackers
Our Apple award-winning MacBook Price Trackers are continually updated with the latest information on prices, bundles, and availability for 16″ and 14″ MacBook Pros along with 13″ and 15″ MacBook... Read more
Every model of Apple’s 13-inch M3 MacBook Air...
Best Buy has Apple 13″ MacBook Airs with M3 CPUs in stock and on sale today for $100 off MSRP. Prices start at $999. Their prices are the lowest currently available for new 13″ M3 MacBook Airs among... Read more

Jobs Board

Solutions Engineer - *Apple* - SHI (United...
**Job Summary** An Apple Solution Engineer's primary role is tosupport SHI customers in their efforts to select, deploy, and manage Apple operating systems and Read more
DMR Technician - *Apple* /iOS Systems - Haml...
…relevant point-of-need technology self-help aids are available as appropriate. ** Apple Systems Administration** **:** Develops solutions for supporting, deploying, Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.