Documentation  |   Table of Contents   |  < Previous   |  Next >   |  Index

4    User Interface

Palm OS® Programmer's Companion

Volume I

     

This chapter describes the user interface (UI) elements that you can use in your application. To create a user interface element, you create a resource that defines what that element looks like and where it is displayed. You interact with the element programmatically as a UI object. A Palm OS® UI object is a C structure that is linked with one or more items on the screen. Note that Palm UI objects are just structures, not the more elaborate objects found in some systems. This is useful because in general a C structure is more compact than these other objects.

This chapter introduces each of the user interface objects. It also describes Palm system managers that aid in working with the user interface. The chapter covers:

For guidelines on designing a user interface, see the book Palm OS User Interface Guidelines.


TIP: The Palm OS web site contains recipes for writing code to work with the various user interface objects. See the following URL: http://www.palmos.com/dev/support/docs/recipes

Palm OS Resource Summary ^TOP^

The Palm OS development environment provides a set of resource templates that application developers use to implement the buttons, dialogs, and other UI elements. Table 4.1 maps user interface elements to resources. The ResEdit name is included for developers using that tool. It is not relevant for users of Constructor for Palm OS.

All resources are discussed in detail in the book Palm OS User Interface Guidelines. In addition, specific design recommendations are provided for some of the elements.

Table 4.1  UI resource summary 

UI Element and Functionality

Example

Resource(s)

Alert—

Display a warning, error, or confirmation message

Alert (Talt)

Application icon—

Icon to display in Launcher

Application icon (tAIB)

Application icon family (taif)

Bitmap—

Display a bitmap

Form bitmap (tFBM)

Bitmap (Tbmp)

Bitmap family (tbmf)

Command button—

Execute command

Button (tBTN)

Graphic button (tgbn)

Check box—

Toggle on or off

Checkbox (tCBX)

Form—

Window that displays other UI objects

Gadget—

Custom control

Gadget (tGDT)

Shift Indicator—

Display shift status

Shift Indicator (tGSI)

Label—

Display noneditable text

Label (tLBL)

List—

Display a series of items

List (tLST)

Menu—

Execute commands

Menu Bar (MBAR)

Menu (MENU)

Pop-up list—

Choose a setting from a list

Pop-up trigger (tPUT)

Pop-up list (tPUL)

List (tLST)

Push button—

Select a value

Push button (tPBN)

Graphic push button (tgpb)

Repeating button —

Increment/decrement values or scroll

Repeating button (tREP)

Graphic repeating button (tgrb)

Scroll bar—

Scroll fields or tables

Scroll bar (tSCL)

Selector trigger —

Invoke dialog that changes text of the control

Selector trigger (tSLT)

Slider—

Adjust a setting

Slider (tsld)

Feedback slider (tslf)

Table—

Display columns of data

Table (tTBL)

Text field—

Display text (single or multiple lines)

Field (tFLD)

Drawing on the Palm Powered Handheld ^TOP^

The first Palm Powered handhelds had an LCD screen of 160x160 pixels. Since then, handhelds with screens resolutions of 320x320 and 320x240 pixels have been introduced. The built-in LCD controller maps a portion of system memory to the LCD. The capabilities of the controller depend on the particular handheld, but be aware that hardware may still limit the actual displayable depths. Given that, Table 4.2 lists the screen bit depths that the Palm OS supports.

Table 4.2  Supported bit depths 

Palm OS Version

Supported Resolutions

1.0

1 bit/pixel

2.0

1 bit/pixel

3.0

1 or 2 bits/pixel

3.3

1, 2, or 4 bits/pixel

3.5

1, 2, 4 or 8 bits/pixel

4.x, 5.x

1, 2, 4, 8, or 16 bits/pixel

(See "Color and Grayscale Support" for more information.)

Usually, the Form Manager handles all necessary drawing and redrawing to the screen when it receives certain events. (In Palm OS, a form is analogous to a window in a desktop application, and a window is an abstract drawing region.) You don't have to explicitly call drawing routines. However, if you're performing animation or if you have any custom user interface objects (known as gadgets), you might need to use the drawing functions provided by the Window Manager.

The Window Manager defines a window object and provides functions for drawing to windows. A window is a drawing region that is either onscreen or offscreen. The window's data structure contains a bitmap that contains the actual data displayed in the window. Windows add clipping regions over the top of bitmaps.

The Draw State ^TOP^

The Window Manager also defines a draw state: pen color, pattern, graphics state, and so on. The draw state is handled differently depending on the operating system version.

On pre-3.5 versions of Palm OS, the system maintains several individual global variables that each track an element of the draw state. If you want to change some aspect of the draw state, you use a WinSet... function (such as WinSetUnderlineMode). Each WinSet... function returns the old value. It's your responsibility to save the old value returned by the function and to restore the variable's value when you are finished by calling the function again. Using such routines can be inconvenient because it means using application stack space to track system state. Further, if a caller forgets to restore the value, the entire look and feel of the handheld may be altered.

Palm OS 3.5 and later has two improvements to make tracking changes to the draw state easier. First, it groups the drawing-related global variables and treats them as a single unit. This draw state is the Palm OS implementation of a pen. It contains the current transfer (or draw) mode, pattern mode and pattern data for WinFill... routines, and foreground and background colors. It also contains text-related drawing information: the font ID, the font pointer, the underline mode, and the text color. (Palm OS does not currently support other common pen-like concepts such as line width, pen shape, or corner join.) Only one draw state exists in the system.

Second, Palm OS 3.5 can track changes to the draw state by storing states on a stack. Your application no longer needs to use its own stack for pieces of the draw state. Instead, use WinPushDrawState to push a copy of the current draw state on the top of the stack. Then use the existing WinSet... functions to make your changes. When you've finished your drawing and want to restore the draw state, call WinPopDrawState.

The new drawing state stack allows for additional debugging help. If an application exits without popping sufficiently or it pops too much, this is detected and flagged on debug ROMs. When switching applications, the system pops to a default state on application exit, guaranteeing a consistent draw state when a new application is launched.

Drawing Functions ^TOP^

The Window Manager can draw rectangles, lines, characters, bitmaps, and (starting in version 3.5) pixels. The Window Manager supports five flavors of most calls, as described in Table 4.3.

Table 4.3  Window Manager drawing operations 

Mode

Operation

Draw

Render object outline only, using current foreground color and pattern. For a bitmap, draws the bitmap.

Fill

Render object internals only, using current foreground color and pattern.

Erase

Erase object outline and internals to window background color.

Invert

Swap foreground and background colors within region defined by object.

Paint

Supported only in version 3.5 and higher. Render object using all of the current draw state: transfer mode, foreground and background colors, pattern, font, text color, and underline mode.

The drawing functions always draw to the current draw window. This window may be either an onscreen window or an offscreen window. Use WinSetDrawWindow to set the draw window before calling these functions.

High-Density Displays ^TOP^

The screens on most Palm Powered handhelds are 160 pixels wide and 160 pixels high. Prior to the High-Density Display Feature Set, the operating system provided little support for other screen sizes. The High-Density Display feature set adds support for 320 by 320, or double-density, displays, and the 1.5x Display Feature Set adds additional support for 320 by 2401, or 1.5x, high-density displays. This support is designed so that a Palm Powered handheld with a double-density screen runs, unaltered, nearly all applications designed for a single-density (160 by 160) screen.

Display Density

The density of a display refers to the ratio of the screen's width and height, in number of pixels, to the width and height of a standard 160 by 160 pixel screen. The screen's density has no relation to the screen's physical size; given the form factor of the typical Palm Powered handheld, screens tend to be roughly the same size regardless of the display density.

A double-density screen packs twice as many pixels in each dimension into the same physical space as a single-density screen. Regardless of the screen density, graphic primitives have the same footprint, taking up the same percentage of screen space. The Address Book application, for example, shows 11 lines of text on both single- and double-density screens. The text looks better on the double-density screen, however, because the blitter uses double-density font data when drawing the text, and each character is composed of more pixels.


NOTE: The High-Density Display feature set is designed to allow screen sizes of various densities. The Palm OS Garnet blitter, however, only supports single-, 1.5-, and double-density displays.

When writing applications for Palm OS handhelds, you generally can stop thinking in terms of pixels and start thinking in terms of screen coordinates. The operating system takes care of mapping coordinates to physical pixels, and drawing functions now work in terms of coordinates. So, for example, if you draw a line of text using one of the built-in fonts, that line of text is 12 standard coordinates high. Depending on the display density, that text might be 12 pixels high, 24 pixels high (on a double-density display), or even some other multiple of 12.

Terminology

A clear understanding of the following terms is essential to understanding the concepts introduced by the High-Density Display feature set.

default density
A pixel layout with one pixel per standard coordinate.
high density
A pixel layout that uses more pixels per standard coordinate than a low-density layout.
low density
Equivalent to default density; one pixel per standard coordinate.
native coordinate system
A coordinate system based on the density of the draw window; when drawing to the screen, this matches the density of physical screen pixels. For offscreen windows, the native coordinates are based on the density of the offscreen bitmap rather than the physical screen.
standard coordinate system
The coordinate system used by most handhelds that don't have the High-Density Display feature set installed. On a single density screen, there is one screen pixel per standard coordinate. On a high-density screen, there is more than one screen pixel per standard coordinate.

Implementation

Applications running on Palm OS default to the standard coordinate system, even if the handheld has a high-density screen. When creating forms, you continue to use the standard coordinate system for form dimensions and for the placement of UI widgets.

In Palm OS, every drawing operation uses a draw state. Added to this draw state by the High-Density Display feature set is a scaling factor, which is used by the Window Manager to transform coordinates passed as arguments to the drawing functions (such as WinDrawLine, WinCopyRectangle, and WinPaintPixel) into native coordinates. This scaling factor is a ratio of the active coordinates to native coordinates.

Drawing is a function of the Window Manager, which initializes the graphic state and then calls the blitter—the low-level code that draws lines and rectangles and places all primitives at the appropriate location on the screen. The Window Manager converts coordinates passed as drawing function arguments from the window's coordinate system to the native coordinate system used by the blitter. Because the blitter needs integer coordinates, most of the WinScale... and WinUnscale... functions have a ceiling parameter that lets you control whether the integer results are obtained by truncation or rounding2. WinScaleRectangle and WinUnscaleRectangle are the exceptions to this rule: the calculated extent is always rounded up if either the extent or the top left coordinate has a fractional part after scaling.

Using WinSetCoordinateSystem, an application can define the coordinate system used by its calls to the drawing functions. On a handheld with a high-density screen, this allows applications to draw using either the standard coordinate system or the native coordinate system. Note that the bounds and clippingBounds fields in the WindowType data structure are always stored using native coordinates. The various functions that access these fields convert the native coordinates to the coordinate system being used by the window.

Which coordinate system a window uses affects the placement and dimensions of graphic primitives. It does not affect bitmap contents, however. You can create bitmaps that contain either low- or high-density bitmap data; the bitmap's density is recorded in the BitmapTypeV3 data structure. The Window Manager uses the window's coordinate system to determine where to place the top left corner of the bitmap on the screen, while the blitter uses the bitmap structure's density field to determine if it needs to stretch or shrink the bitmap data as it blits.

As an example, suppose you have an application that draws a low-density bitmap containing data 30 pixels wide and 70 pixels high on a Palm Powered handheld with a double-density screen. Using the standard coordinate system, the application instructs the Window Manager to place the bitmap at window coordinates (10,20). The Window Manager converts (10,20) to native coordinates and instructs the blitter to draw the bitmap at native coordinates (20,40). Recognizing that the bitmap is low density, the blitter pixel-doubles the source data as it is blitted. The result is that on the double-density screen, the bitmap is displayed with 60 pixels per row and contains 140 rows.

Regardless of the coordinate system used for the placement and dimensions of graphic primitives, no new functions are needed to take advantage of high-density fonts. High-density fonts are used by default when drawing text in a high-density window.


NOTE: Scaling of fonts and bitmaps can be disabled on high-density handhelds running more recent versions of the Palm OS, allowing applications to display more of a large graphic or to display more text at one time. For details, see the documentation for WinSetScalingMode in the Palm OS Programmer's API Reference.

When working with 1.5x displays, how scaling is performed has implications for how you write your applications. The Window Manager uses fixed-point arithmetic to convert standard coordinates to native coordinates. Standard coordinates are scaled using the "ceiling" function, which causes values to be scaled as follows when working with a 1.5x display:

Standard

Native

1

2

2

3

3

5

4

6

5

8

6

9

If an application uses standard coordinates, but also wants a group of lines, pixels, or bitmaps to be evenly spaced, then the coordinates should be separated by an even number of standard pixels. For example, the sequence of standard coordinates separated by 3 pixels {1, 4, 7, 10, ...} is scaled to the uneven sequence {2, 6, 11, 15, ...}, with successive members separated by either 4 or 5 native pixels. In contrast, the sequence of standard coordinates separated by 2 pixels {1, 3, 5, 7, ...} is scaled to the sequence {2, 5, 8, 11, ...}, whose members are consistently separated by 3 native pixels.


NOTE: The scaling algorithm used on Palm OS Cobalt is slightly different; see footnote 2. for details.

Rectangles are scaled using a different algorithm that ensures consistency for both the origin and the extent of each side, so that a rectangle that is scaled and then unscaled is equal to the original rectangle.

When using standard coordinates for frames, the Window Manager uses the "floor" function. This causes values to be scaled as follows when working with a 1.5x display:

Standard

Native

1

1

2

3

3

4

4

6

5

7

6

9

The floor function is also used to scale the frame's width.

Push buttons and graphic buttons are user interface controls that are composed of rectangles that share a frame edge. To avoid rounding inconsistencies on 1.5x displays, the buttons' topLeft.x should be placed on an even standard coordinate, and the buttons' width should be odd standard coordinates for horizontally arranged buttons, and the buttons' height should be odd standard coordinates for vertically arranged buttons. This avoids the uneven appearance of every other button frame lying alongside rather than on top of its neighbor's frame. Both rules should be applied for a push button grid, where columns and rows of push buttons share more than one common edge.

When a low-density bitmap is blitted to a 1.5x destination bitmap, the blitter doubles every other pixel in each row, and doubles every other row. Note that applications must always include low-density bitmaps: the blitter doesn't scale 1.5x to double-density, and vice-versa.


WARNING! The blitter's behavior when attempting to draw double-density data (text or bitmap) to a 1.5x destination, or attempting to draw 1.5x data to a double-density destination, is undefined. Drawing low-density font or bitmap data to a high-density destination (either 1.5 or double density), however, works as expected.

If your application must present the highest-quality bitmaps, it should incorporate bitmap families with members for all supported densities. If quality is less important than application size, you may wish to include only a subset of the supported densities (but at a minimum you must include low-density versions).

Avoid algorithms that capture high-density screen data to a low density offscreen window, and then restore the offscreen window to the screen. This results in a loss of data when scaling down, and a further distortion when scaling back up. Instead, allocate the offscreen window using WinCreateOffscreenWindow with the nativeFormat argument. This allocates a bitmap for the offscreen window that matches the density of the screen.

Because fonts are drawn as bitmaps, the rules that apply to bitmaps apply to application-defined fonts as well.

Maintaining Compatibility

The High-Density Display Feature Set is designed to ensure the greatest degree of compatibility with applications that weren't written using the High-Density Display feature set. When running in low-density mode on a handheld with a high-density screen, the window's scale attribute is set to the ratio of the handheld's screen density to the default density. This causes the Window Manager to scale the low-density coordinates used to position graphic primitives into high-density ones used by the blitter. Because low-density mode is the default on all Palm Powered handhelds, applications not designed for high-density screens behave as expected on handhelds with screens of both low and high-density.

Offscreen windows are allocated by default with low-density bitmaps, so direct manipulation of offscreen bitmaps by applications unaware of the High-Density Displays feature set works consistently on handhelds with either low- or high-density screens.

On the other hand, applications that employ the High-Density Display feature set need to include both low-density and high-density bitmaps in order to function consistently on handhelds that don't have high-density displays.

Some Sony CLIE'™ handhelds have a double-density screen but don't have the High-Density Display feature set. The High-Density Display feature set recognizes bitmaps created for these handhelds and properly displays them as double-density bitmaps.

The one area of incompatibility involves applications that directly access the handheld's screen. Applications not designed for a high-density screen that directly access the screen give unexpected results when accessing a high-density screen. For example, if such an application directly manipulates the screen pixels, expecting a 160 by 160 screen, modifying pixel 161 on a double-density screen modifies a pixel in the middle of the first row, not the first pixel on the second row. As well, if the handheld's processor is ARM-based, improper drawing can also result due to differences in endianness between ARM-based platforms and those based upon a 68k-family processor.

Text

Palm-powered handhelds contain system fonts that match the density of the screen. By default, text is always drawn at the best possible density, even for applications unaware of a handheld's high-density capability. The high-density font metrics match those of the low-density system fonts.

Because the system fonts match the screen density, the blitter does not need to perform scaling when blitting text to the screen. If an application running on a handheld with a high-density screen allocates a low-density offscreen window, however, and there are no low-density fonts available, the blitter shrinks the high-density font bitmaps. This results in poor quality text when the offscreen bitmap is subsequently transferred, and pixel-doubled, to a high-density display. If a low-density font is available, the blitter substitutes a low-density font when drawing text to the window in an attempt to produce the best possible aesthetic result.

The blitter uses the following selection algorithm when selecting the font, from high to low priority:

  1. Select the font with the correct density.
  2. Select the font whose density is one-half of the correct density.
  3. Select the font with the closest density, with a tie going to the lower-density font.

This behavior can be overridden to allow your application to display more text at one time; WinSetScalingMode can force the blitter to use the low-density font, unscaled, for subsequent text drawing. Note that this only works on handhelds with high-density displays running a recent version of Palm OS that supports the WinSetScalingMode function.

The Font Manager uses the stdToActiveScale field in the offscreen window's draw state to transform the font metrics. To draw text using high-density coordinates, set the high-density coordinate system by calling WinSetCoordinateSystem before using the Font Manager functions to position text or extract font metrics.

The blitter by default aligns glyphs on standard coordinates. This behavior works fine with single- and double-density displays, but can cause the spacing between characters to look uneven on "one and a half density" (1.5x) displays. This is because on a 1.5x display, the blitter must add "padding"—extra white space—between some glyphs to align them on standard coordinates. You can override this standard behavior with WinSetScalingMode: it allows you to draw text without padding pixels between glyphs, resulting in more consistent kerning for text. Note, however, that while this unpadded mode provides the best looking text, it requires the application to use the high-density coordinate system.

On a high-density screen, underline mode is always drawn using a high-density pattern.

For an in-depth discussion on working with text in the user interface, see Chapter 8, "Text." It contains an in-depth a discussion on selecting, using, and creating fonts; see "Fonts."

Lines and Rectangles

When drawing lines and rectangles with the standard coordinate system on a double-density screen, the primitives are drawn with improved resolution. This behavior prevents an inconsistent appearance when drawing to and from offscreen windows, and prevents unintended overlap and unintended gaps between primitives.

As with other primitives, the Window Manager performs the conversion to the destination coordinate system before calling the blitter. This converts line coordinates as well as a rectangle's topLeft and extent fields.

The diagram on the left in Figure 4.1 results from drawing a diagonal line from (2,1) to (6,3) in the screen's standard coordinate system. The diagram on the right shows the same line drawn in the screen's native coordinate system with the following code:


WinPushDrawState(); 
oldScale = WinSetCoordinateSystem(kCoordinatesNative); 
WinDrawLine(2, 1, 6, 3);  // x1, y1, x2, y2 
WinPopDrawState(); 


NOTE: In these illustrations, the top-left grid coordinate is the screen origin (0,0) on a double-density screen.

Figure 4.1  A diagonal line drawn using the standard coordinate system (left) and the native coordinate system (right)

The result of drawing a rectangle with a topLeft of (1,1) and an extent of (4,4) when using the standard and native coordinate systems on a double-density screen is shown in Figure 4.2.

Figure 4.2  A rectangle drawn using the standard coordinate system (left) and the native coordinate system (right)

A rounded rectangle would be pixel-doubled in a similar fashion when drawn using the standard coordinate system on a double-density screen. In double-density mode, the rounded corners are drawn in the native double-density coordinates, resulting in more detailed corners.

Patterns

In prior versions of the Palm OS, patterns are 8 by 8 bits, and are 1 bit deep. To support high-density patterns, a new Window Manager function, WinPaintTiledBitmap, gives applications the ability to fill a rectangle with an arbitrary pattern defined in a bitmap argument.

Patterns are expanded to the destination bit depth by the blitter when drawing patterned lines and filled rectangles. The blitter uses the density fields in the pattern's source bitmap and the destination bitmap so that the pattern is drawn using the appropriate density. This makes it possible for an application to define both low-density and high-density patterns.

To supplement the standard PatternType grayPattern, the High-Density Display feature set defines two additional gray patterns: lightGrayPattern and darkGrayPattern. These patterns are shown in Figure 4.3 and Figure 4.4, respectively.

Figure 4.3  lightGrayPattern

Figure 4.4  darkGrayPattern

These three standard gray patterns are always drawn by the blitter using the screen density, improving the appearance of gray fills. Custom 8 by 8 patterns, however, are stretched as appropriate by the blitter based on the ratio of the destination density and kDensityLow.

Forms, Windows, and Dialogs ^TOP^

A form is the GUI area for each view of your application. For example the Address Book offers an Address List view, Address Edit view, and so on. Each application has to have one form, and most applications have more than one. To actually create the view, you have to add other UI elements to the form; either by dragging them onto the form from the catalog or by providing their ID as the value of some of the form's fields.

Figure 4.5 shows an example of a form. Typical forms are as large as the screen, as shown here. Other forms are modal dialogs, which are shorter than the screen but just as wide.

Figure 4.5  Form

A window defines a drawing region. This region may be on the display or in a memory buffer (an off-screen window). Off-screen windows are useful for saving and restoring regions of the display that are obscured by other UI objects. All forms are windows, but not all windows are forms.

The window object is the portion of the form object that determines how the form's window looks and behaves. A window object contains viewing coordinates of the window and clipping bounds.

When a form is opened, a frmOpenEvent is triggered and the form's ID is stored. A winExitEvent is triggered whenever a form is closed, and a winEnterEvent is triggered whenever a form is drawn.

The following sections describe special types of forms:

Alert Dialogs ^TOP^

If you want to display an alert dialog (see Figure 4.6) or prompt the user for a response to a question, use the alert manager. The alert manager defines the following functions:

Figure 4.6  Alert dialog

Given a resource ID that defines an alert, the alert manager creates and displays a modal dialog box. When the user taps one of the buttons in the dialog, the alert manager disposes of the dialog box and returns to the caller the item number of the button the user tapped.

There are four types of system-defined alerts:

  • Question
  • Warning
  • Notification
  • Error

The alert type determines which icon is drawn in the alert window and which sound plays when the alert is displayed.

When the alert manager is invoked, it's passed an alert resource that contains the following information:

  • The rectangle that specifies the size and position of the alert window
  • The alert type (question, warning, notification, or error)
  • The null-terminated text string; that is, the message the alert displays
  • The text labels for one or more buttons

Progress Dialogs ^TOP^

If your application performs a lengthy process, such as data transfer during a communications session, consider displaying a progress dialog to inform the user of the status of the process. The Progress Manager provides the mechanism to display progress dialogs.

You display a progress dialog by calling PrgStartDialog. Then, as your process progresses, you call PrgUpdateDialog to update the dialog with new information for the user. In your event loop you call PrgHandleEvent to handle the progress dialog update events queued by PrgUpdateDialog. The PrgHandleEvent function makes a callback to a textCallback function that you supply to get the latest progress information.

Note that whatever operation you are doing that is the lengthy process, you do the work inside your normal event loop, not in the callback function. That is, you call EvtGetEvent and do work when you get a nilEvent. Each time you get a nilEvent, do a chunk of work, but be sure to continue to call EvtGetEvent frequently (like every half second), so that pen taps and other events get noticed quickly enough.

The dialog can display a few lines of text that are automatically centered and formatted. You can also specify an icon that identifies the operation in progress. The dialog has one optional button that can be a cancel or an OK button. The type of the button is automatically controlled by the Progress Manager and depends on the current progress state (no error, error, or user canceled operation).

Progress textCallback Function

When you want to update the progress dialog with new information, you call the function PrgUpdateDialog. To get the current progress information to display in the progress dialog, PrgHandleEvent makes a callback to a function, textCallback, that you supplied in your call to PrgStartDialog.

The system passes the textCallback function one parameter, a pointer to a PrgCallbackData structure. To learn what type of information is passed in this structure, see the chapter "Progress Manager" in the Palm OS Programmer's API Reference.

Your textCallback function should return a Boolean. Return true if the progress dialog should be updated using the values you specified in the PrgCallbackData structure. If you specify false, the dialog is still updated, but with default status messages. (Returning false is not recommended.)

In the textCallback function, you should set the value of the textP buffer to the string you want to display in the progress dialog when it is updated. You can use the value in the stage field to look up a message in a string resource. You also might want to append the text in the message field to your base string. Typically, the message field would contain more dynamic information that depends on a user selection, such as a phone number, device name, or network identifier, etc.

For example, the PrgUpdateDialog function might have been called with a stage of 1 and a messageP parameter value of a phone number string, "555-1212". Based on the stage, you might find the string "Dialing" in a string resource, and append the phone number, to form the final text "Dialing 555-1212" that you place in the text buffer textP.

Keeping the static strings corresponding to various stages in a resource makes it easier to localize your application. More dynamic information can be passed in via the messageP parameter to PrgUpdateDialog.


NOTE: The textCallback function is called only if the parameters passed to PrgUpdateDialog have changed from the last time it was called. If PrgUpdateDialog is called twice with exactly the same parameters, the textCallback function is called only once.

The Keyboard Dialog ^TOP^

The keyboard dialog is an onscreen keyboard on which the user taps to input information into a text field. When the insertion point is in a text field, the user can open the onscreen keyboard by tapping on the silk-screen letters ("abc" or "123") in the lower corners of the input area. The keyboard dialog appears:

Figure 4.7  The Keyboard Dialog

The keyboard dialog's text field contains the full text of the original field, with the insertion point in the same position as in the original field. Users can start inserting and deleting characters immediately, or they can scroll up or down and then insert and delete. When one of the software keys is tapped, the corresponding character is inserted in the text field of the keyboard dialog.

As the user taps, the keyboard dialog code captures pen events, maps them to characters, and posts keyDownEvents. The text field in the keyboard dialog handles each keyDownEvent, displaying the character onscreen and inserting it into the memory chunk associated with the field. Since the keyboard dialog has its own event loop, you cannot handle the key events yourself. If you need to capture the key events, you should consider creating a custom version of the onscreen keyboard dialog, as outlined in "Creating a Custom Keyboard Layout."

The keyboard code edits the text string of the original field in-place. Each field has a text handle that points to the memory chunk containing the text string for the field. When the keyboard dialog is opened, the association between the text handle and the original field is removed. The text handle is then assigned to the text field of the keyboard dialog and edited according to user input. When the keyboard dialog is closed, the text handle is reassigned to the original field.

For details on how FldHandleEvent manipulates the memory chunk that holds a field's text string, see Chapter 9, "Fields," in the Palm OS Programmer's API Reference. Read about the FldGetTextHandle and FldSetText functions.

Opening the Keyboard Dialog Programmatically

In most applications, the keyboard dialog appears only when explicitly opened by the user. There are occasions, however, when you may wish to force the user to input characters via the onscreen keyboard. For example, the service activation application shipped with all Palm VIIs displays the keyboard dialog automatically. Palm made this choice because the activation application must be usable by completely new Palm users, who may not know how to write Graffiti® or Graffiti® 2 or open the keyboard dialog themselves. Other reasons for imposing the keyboard dialog include accurate input of passwords or account numbers.

To display the keyboard dialog programmatically, use one of the following functions:

Normally, use SysKeyboardDialog only. SysKeyboardDialogV10 is for compatibility with Palm OS 1.0.

See Keyboard.h for the function prototypes and the KeyboardType they use. Note that the rest of the functions listed in Keyboard.h are for system use only and do not form part of the Palm OS API.

Keyboard Layouts

The keyboard dialog has three views, one for each of the pre-defined layouts: the English alphabet, numerals and punctuation, and Latin characters with diacritic marks. The default is the English alphabet. To display a particular layout, call the SysKeyboardDialog function and pass it one of the following constants, which are defined in an enumeration named KeyboardType:

Table 4.4  Constants defined in KeyboardType  

Constant

Character Set

kbdAlpha

The English language character set.

kbdNumbersAndPunc

A set containing numbers and some advanced punctuation.

kbdAccent

The International character set, made up of Latin characters with diacritic marks.

kbdDefault

The value of kbdDefault is the same as kdbAlpha and cannot be changed.

Creating a Custom Keyboard Layout

You cannot add an extra keyboard layout or modify an existing one. You can, however, create your own keyboard dialog module that implements the functionality outlined below.

First, your application should intercept the keyDownEvent generated when the user taps the "abc" or "123" letters in the input area. Create a custom keyboard dialog loader routine to handle it. Your keyboard code should then do the following:

  • Get the text handle of the original field and save it in a variable. Use FldGetTextHandle.
  • Remove the association between the text handle and the original field. Use FldSetTextHandle or FldSetText, passing NULL as the second argument.
  • Assign the text handle to the text field of the keyboard dialog.
  • Define a Keyboard event handler that:
    • captures pen events in your onscreen keyboard region, which may be a bitmap of a keyboard or may consist of individual push buttons,
    • maps pen events to characters,
    • creates keyDownEvents and posts them to the event queue so that the dialog's text field can automatically handle them and insert them in its text chunk.
  • When the dialog is closed, remove the association between the text handle and keyboard's field, and then re-assign the text handle to the original text field.

Finally, if you wish more than one layout, your custom keyboard dialog must contain a button to open each layout.

Offscreen Windows ^TOP^

Offscreen windows are generally used for one of two reasons: to do offscreen drawing (for double-buffering, smooth animations, or to reduce flicker) or so that the application can capture or import graphics.

WinCreateOffscreenWindow allocates a bitmap for the offscreen window. Unless you specify a format of nativeFormat, the offscreen window's bitmap is always low density. This allows applications that expect low-density bitmaps, and that directly manipulate bitmap data, to still function as expected. If you call WinCreateOffscreenWindow and specify a format of nativeFormat, do not access the data in the offscreen window's bitmap directly: the format of bitmaps created by Palm OS can change from release to release, from device to device, and may even differ on a single device depending on the screen depth or compatibility mode.

Functions that return window dimensions—such as WinScreenMode, WinGetBounds, and WinGetDrawWindowBounds—use the window's scaling factor to return coordinates in terms of the active coordinate system. This ensures that the window has the expected dimensions and that graphic primitives have coordinates expected by the application.

WinCreateBitmapWindow gives you the ability to allocate a high-density bitmap for an offscreen window. Use BmpCreate and BmpSetDensity to allocate a high-density bitmap, then associate it with a window by calling WinCreateBitmapWindow.

Controls ^TOP^

Control objects allow for user interaction when you add them to the forms in your application. Events in control objects are handled by CtlHandleEvent. There are several types of control objects, which are all described in this section.


NOTE: Palm OS 3.5 and later support graphical controls for all control types other than check box. Graphical controls behave the same as their non-graphical counterparts, but they display a bitmap instead of a text label. On releases prior to Palm OS 3.5, you can create a graphical control by setting the text label to the empty string and placing the control on top of a bitmap.

Buttons ^TOP^

Buttons (see Figure 4.8) display a text or graphic label in a box. The default style for a button is a text string centered within a rounded rectangle. Buttons have rounded corners unless a rectangular frame is specified. A button without a frame inverts a rectangular region when pressed.

When the user taps a button with the pen, the button highlights until the user releases the pen or drags it outside the bounds of the button.

Table 4.5 shows the system events generated when the user interacts with the button and CtlHandleEvent's response to the events.

Figure 4.8  Buttons

Table 4.5  Event flow for buttons 

User Action

System Response

CtlHandleEvent Response

Pen goes down on a button.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with button's ID number.

Inverts the button's display.

Pen is lifted from button.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlSelectEvent to the event queue.

Pen is lifted outside button.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlExitEvent to the event queue.

Pop-Up Trigger ^TOP^

A pop-up trigger (see Figure 4.9) displays a text label and a graphic element (always on the left) that signifies the control initiates a pop-up list. If the text label changes, the width of the control expands or contracts to the width of the new label plus the graphic element.

Table 4.6 shows the system events generated when the user interacts with the pop-up trigger and CtlHandleEvent's response to the events. Because pop-up triggers are used to display list objects, also see the section "Lists" in this chapter.

Figure 4.9  Pop-up trigger

Table 4.6  Event flow for pop-up triggers 

User Action

System Response

CtlHandleEvent Response

Pen goes down on the pop-up trigger.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with pop-up trigger's ID number.

Inverts the trigger's display.

Pen is lifted from button.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlSelectEvent to the event queue.

ctlSelectEvent with pop-up trigger's ID number.

Adds a winEnterEvent for the list object's window to the event queue. Control passes to FrmHandleEvent, which displays the list and adds a popSelectEvent to the event queue. Control then passes to LstHandleEvent.

Pen is lifted outside button.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlExitEvent to the event queue.


TIP: To create a pop-up list in Constructor for Palm OS, add a pop-up trigger to your form, then add a list at the same coordinates, uncheck the usable check box in the list resource settings, and then set the List ID in the pop-up trigger to match the ID of the list resource.

Selector Trigger ^TOP^

A selector trigger (see Figure 4.10) displays a text label surrounded by a gray rectangular frame. If the text label changes, the width of the control expands or contracts to the width of the new label.

Table 4.7 shows the system events generated when the user interacts with the selector trigger and CtlHandleEvent's response to the events.

Figure 4.10  Selector trigger

Table 4.7  Event flow for selector triggers 

User Action

System Response

CtlHandleEvent Response

Pen goes down on a selector trigger.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with selector trigger's ID number.

Inverts the button's display.

Pen is lifted from the selector trigger.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlSelectEvent to the event queue.

ctlSelectEvent with selector trigger's ID number.

Adds a frmOpenEvent followed by a winExitEvent to the event queue. Control is passed to the form object.

Repeating Button ^TOP^

A repeat control looks like a button. In contrast to buttons, however, users can repeatedly select repeat controls if they don't lift the pen when the control has been selected. The object is selected repeatedly until the pen is lifted.

Table 4.8 shows the system events generated when the user interacts with the repeating button and CtlHandleEvent's response to the events.

Table 4.8  Event flow for repeating buttons 

User Action

System Response

CtlHandleEvent Response

Pen goes down on a repeating button.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with button's ID number.

Adds the ctlRepeatEvent to the event queue.

Pen remains on repeating button.

ctlRepeatEvent

Tracks the pen for a period of time, then sends another ctlRepeatEvent if the pen is still within the bounds of the control.

Pen is dragged off the repeating button.

No ctlRepeatEvent occurs.

Pen is dragged back onto the button.

ctlRepeatEvent

See above.

Pen is lifted from button.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlExitEvent to the event queue.

Push Buttons ^TOP^

Push buttons (see Figure 4.11) look like buttons, but the frame always has square corners. Touching a push button with the pen inverts the bounds. If the pen is released within the bounds, the button remains inverted.

Table 4.9 shows the system events generated when the user interacts with the push button and CtlHandleEvent's response to the events.

Figure 4.11  Push buttons

.

Table 4.9  Event flow for push buttons 

User Action

System Response

CtlHandleEvent Response

Pen goes down on a push button.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with push button's ID number.

If push button is grouped and highlighted, no change. If push button is ungrouped and highlighted, it becomes unhighlighted.

Pen is lifted from push button.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlSelectEvent to the event queue.

Check Boxes ^TOP^

Check boxes (see Figure 4.12) display a setting, either on (checked) or off (unchecked). Touching a check box with the pen toggles the setting. The check box appears as a square, which contains a check mark if the check box's setting is on. A check box can have a text label attached to it; selecting the label also toggles the check box.

Table 4.10 shows the system events generated when the user interacts with the check box and CtlHandleEvent's response to the events.

Figure 4.12  Check boxes

Table 4.10  Event flow for check boxes 

User Action

Event Generated

CtlHandleEvent Response

Pen goes down on check box.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with check box's ID number.

Tracks the pen until the user lifts it.

Pen is lifted from check box.

penUpEvent with the x and y coordinates stored in EventType.

  • If the check box is unchecked, a check appears.
  • If the check box is already checked and is grouped, there is no change in appearance.
  • If the check box is already checked and is ungrouped, the check disappears.

Adds the ctlSelectEvent to the event queue.

Pen is lifted outside box.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlExitEvent to the event queue.

Sliders and Feedback Sliders ^TOP^

Starting in Palm OS 3.5, slider controls (see Figure 4.13) are supported. Sliders represent a value that falls within a particular range. For example, a slider might represent a value that can be between 0 and 10.

Figure 4.13  Slider

There are four attributes that are unique to slider controls:

  • The minimum value the slider can represent
  • The maximum value the slider can represent
  • The current value
  • The page jump value, or the amount by which the value is increased or decreased when the user clicks to the left or right of the slider thumb

Palm OS supports two types of sliders: regular slider and feedback slider. Sliders and feedback sliders look alike but behave differently. Specifically, a regular slider control does not send events while the user is dragging its thumb. A feedback slider control sends an event each time the thumb moves one pixel, whether the pen has been lifted or not.

Table 4.11 shows the system events generated when the user interfaces with a slider and how CtlHandleEvent responds to the events.

Table 4.11  Event flow for sliders 

User Action

System Response

CtlHandleEvent Response

Pen tap on slider's background.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with slider's ID number.

Adds or subtracts the slider's page jump value from its current value, and adds a ctlSelectEvent with the new value to the event queue.

Pen goes down on the slider's thumb.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with slider's ID number.

Tracks the pen.

Pen drags slider's thumb to the left or right.

Continues tracking the pen.

Pen is lifted from slider.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlSelectEvent with the slider's ID number and new value if the coordinates are within the bounds of the slider.

Adds the ctlExitEvent if the coordinates are outside of the slider's bounds.

Table 4.12 shows the system events generated when the user interacts with a feedback slider and CtlHandleEvent's response to the events.

Table 4.12  Event flow for feedback sliders 

User Action

System Response

CtlHandleEvent Response

Pen tap on slider's background.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with slider's ID number.

Adds or subtracts the slider's page jump value from its current value and then sends a ctlRepeatEvent with the slider's new value.

ctlRepeatEvent

Adds or subtracts the slider's page jump value from its current value repeatedly until the thumb reaches the pen position or the slider's minimum or maximum. Then sends a ctlSelectEvent with slider's ID number and new value.

Pen goes down on the slider's thumb.

penDownEvent with the x and y coordinates stored in EventType.

Adds the ctlEnterEvent to the event queue.

ctlEnterEvent with slider's ID number.

Tracks the pen and updates the display.

Pen drags slider's thumb to the left or right.

ctlRepeatEvent with slider's ID number and new value.

Tracks the pen. Each time pen moves to the left or right, sends another ctlRepeatEvent if the pen is still within the bounds of the control.

Pen is dragged off the slider vertically.

ctlRepeatEvent with the slider's ID number and old value.

Pen is dragged back onto the slider.

ctlRepeatEvent with the slider's ID number and new value.

Pen is lifted from slider.

penUpEvent with the x and y coordinates stored in EventType.

Adds the ctlExitEvent to the event queue.

Sliders are drawn using two bitmaps: one for the slider background, and the other for the thumb. You may use the default bitmaps to draw sliders, or you may specify your own bitmaps when you create the slider.

The background bitmap you provide can be smaller than the slider's bounding rectangle. This allows you to provide one bitmap for sliders of several different sizes. If the background bitmap isn't as tall as the slider's bounding rectangle, it's vertically centered in the rectangle. If the bitmap isn't as wide as the slider's bounding rectangle, the bitmap is drawn twice. First, it's drawn left-justified in the left half of the bounding rectangle and clipped to exactly half of the rectangle's width. Then, it's drawn right-justified in the right half of the bounding rectangle and clipped to exactly half of the rectangle's width. (See Figure 4.14.) Note that this means that the bitmap you provide must be at least half the width of the bounding rectangle.

Figure 4.14  Drawing a slider background

Fields ^TOP^

A field object displays one or more lines of text. Figure 4.15 is an underlined, left-justified field containing data.

Figure 4.15  Field

The field object supports these features:

  • Proportional fonts (only one font per field)
  • Drag-selection
  • Scrolling for multiline fields
  • Cut, copy, and paste
  • Left and right text justification
  • Tab stops
  • Editable/noneditable attribute
  • Expandable field height (the height of the field expands as more text is entered)
  • Underlined text (each line of the field is underlined)
  • Maximum character limit (the field stops accepting characters when the maximum is reached)
  • Special keys (Graffiti and Graffiti 2 strokes) to support cut, copy, and paste
  • Insertion point positioning with pen (the insertion point is positioned by touching the pen between characters)
  • Scroll bars

The field object does not support overstrike input mode; horizontal scrolling; numeric formatting; or special keys for page up, page down, left word, right word, home, end, left margin, right margin, and backspace. On Palm OS versions earlier than 3.5, the field object also does not support word selection. Starting in version 3.5, double-tapping a word selects that word, and triple-tapping selects the entire line.


NOTE: Field objects can handle line feeds—\0A—but not carriage returns—\0D. PalmRez translates any carriage returns it finds in any Palm OS resources into line feeds, but doesn't touch static data.

Events in field objects are handled by FldHandleEvent. Table 4.13 provides an overview of how FldHandleEvent deals with the different events

Table 4.13  Event flow for fields 

User Action

Event Generated

FldHandleEvent Response

Pen goes down on a field.

penDownEvent with the x and y coordinates stored in EventType.

Adds the fldEnterEvent to the event queue.

fldEnterEvent with the field's ID number.

Sets the insertion point position to the position of the pen and tracks the pen until it is released. Drag-selection and drag-scrolling are supported.

Starting in Palm OS 3.5, double-tapping in a field selects the word at that location, and triple-tapping selects the line.

Pen is lifted.

penUpEvent with the x and y coordinates.

Nothing happens; a field remains selected until another field is selected or the form that contains the field is closed.

Enters characters into selected field.

keyDownEvent with character value in EventType.

Character added to field's text string.

Presses up arrow key

keyDownEvent

Moves insertion point up a line.

Presses down arrow

keyDownEvent

Moves insertion point down a line; the insertion point doesn't move beyond the last line that contains text.

Presses left arrow

keyDownEvent

Moves insertion point one character position to the left. When the left margin is reached, move to the end of the previous line.

Presses right arrow

keyDownEvent

Moves insertion point one character position to the right. When the right margin is reached, move to the start of the next line.

Cut command

keyDownEvent

Cuts the current selection to the text clipboard.

Copy command

keyDownEvent

Copies the current selection to the text clipboard.

Paste command

keyDownEvent

Inserts clipboard text into the field at insertion point.

Menus ^TOP^

A menu bar is displayed whenever the user taps a menu icon. Starting in Palm OS 3.5, the menu bar is also displayed when the user taps in a form's titlebar. The menu bar, a horizontal list of menu titles, appears at the top of the screen in its own window, above all application windows. Pressing a menu title highlights the title and "pulls down" the menu below the title (see Figure 4.16).

Figure 4.16  Menu

User actions have the following effect on a menu:

When...

Then...

User drags the pen through the menu

Command under the pen is highlighted

Pen is released over a menu item

That item is selected and the menu bar and menu disappear

Pen is released outside both the menu bar and the menu

Both menu and menu bar disappear and no selection is made

Pen is released in a menu title (Palm OS 3.5 and later only)

Menu bar and Menu remain displayed until a selection is made from the menu.

Pen is tapped outside menu and menu bar

Both menu and menu bar are dismissed

A menu has the following features:

  • Item separators, which are lines to group menu items.
  • Menu shortcuts; the shortcut labels are right justified in menu items.
  • A menu remembers its last selection; the next time a menu is displayed the prior selection appears highlighted.
  • The bits behind the menu bar and the menus are saved and restored by the menu routines.
  • When the menu is visible, the insertion point is turned off.

Menu events are handled by MenuHandleEvent. Table 4.14 describes how user actions get translated into events and what MenuHandleEvent does in response.

Table 4.14  Event flow for menus 

User Action

Event Generated

MenuHandleEvent Response

Pen enters menu bar.

winEnterEvent identifying menu's window.

Tracks the pen.

User selects a menu item.

penUpEvent with the x and y coordinates.

Adds a menuEvent with the item's ID to the event queue.

Checking Menu Visibility ^TOP^

When the operating system draws a menu, the menu's window becomes the active drawing window. The operating system generates a winExitEvent for the previous active drawing window and a winEnterEvent for the menu's window. When the menu is erased, the system generates a winExitEvent for the menu's window and a winEnterEvent for the window that was active before the menu was drawn.

It's common to want to check if the menu is visible in applications that perform custom drawing to a window. Such applications want to make sure that they don't draw on top of the menu. The recommended way to do this is to stop drawing when you receive a winExitEvent matching your drawing window and resume drawing when you receive the corresponding winEnterEvent. For example, the following code is excerpted from the Reptoids example application's main event loop:


EvtGetEvent (&event, TimeUntillNextPeriod()); 
  
if (event.eType == winExitEvent) { 
  if (event.data.winExit.exitWindow ==  
    (WinHandle) FrmGetFormPtr(MainView)) { 
      // stop drawing.  
  } 
} 
  
else if (event.eType == winEnterEvent) { 
  if (event.data.winEnter.enterWindow ==  
    (WinHandle) FrmGetFormPtr(MainView) && 
    event.data.winEnter.enterWindow ==  
    (WinHandle) FrmGetFirstForm ()) { 
      // start drawing 
  } 
} 

Note that this technique is not specific to menus—your application should stop drawing if any window obscures your drawing window, and it will do so if you check for winEnterEvent and winExitEvent.

Dynamic Menus ^TOP^

In releases of Palm OS prior to release 3.5, the menu was loaded from a menu resource (created with Constructor or some other tool) and could not be modified in code. Starting in Palm OS 3.5, you can add, hide, or unhide menu items while the menu resource is being loaded.

A menuOpenEvent is sent when the menu resource is loaded. (Note that this event is new in version 3.5. Previous releases do not use it.) In response to this event, you can call MenuAddItem to add a menu item to one of the pull-down menus, MenuHideItem to hide a menu item, or MenuShowItem to display a menu item.

You might receive menuOpenEvent several times during an application session. The menu resource is loaded each time the menu is made the active menu. A menu becomes active the first time the user either requests that the menu be displayed or enters the command keystroke on the current form. That menu remains active as long as the form with which it is associated is active. A menu loses its active status under these conditions:

  • When FrmSetMenu is called to change the active menu on the form.
  • When a new form, even a modal form or alert panel, becomes active.

Suppose a user selects your application's About item from the Options menu then clicks the OK button to return to the main form. When the About dialog is displayed, it becomes the active form, which causes the main form's menu state to be erased. This menu state is not restored when the main form becomes active again. The next time the user requests the menu, the menu resource is reloaded, and a new menuOpenEvent is queued.

You should only make changes to a menu the first time it is loaded after a form becomes active. You should not add, hide, or show items based on user context. Such practice is discouraged in the Palm OS user interface guidelines.

Menu Shortcuts ^TOP^

As an alternative to selecting a menu command through the user interface, users can instead enter a menu shortcut. This support is present in all versions of the Palm OS, but it was extended in Palm OS 3.5.

On all versions of Palm OS, the user can enter a Graffiti or Graffiti 2 command keystroke followed by another character. If the next character matches one of the shortcut characters for an item on the active menu, a menuEvent with that menu item is generated. To support this behavior, you simply specify a shortcut character when you create a menu item resource. The default behavior of Palm OS handles this shortcut appropriately.


NOTE: If the Graffiti 2 Feature Set is present, avoid using a multi-stroke character as a keyboard shortcut if its first stroke matches the stroke of another letter (such as the letter "l" or the space character).

Starting in Palm OS 3.5, drawing the command stroke displays the command toolbar (see Figure 4.17). This toolbar is the width of the screen. (Previous versions of Palm OS simply display the string "Command:" in the lower-left portion of the screen.) The command toolbar displays a status message on the left and buttons on the right. After drawing the command stroke, the user has the choice of writing a character or of tapping one of the buttons on the command toolbar. Both of these actions cause the status message to be briefly displayed and (in most cases) a menuEvent to be added to the event queue.

Figure 4.17  Command toolbar

The buttons displayed on the toolbar depend on the user context. If the focus is in an editable field, the Field Manager displays buttons for cut, copy, and paste on the command toolbar. If there is an action to undo, the field manager also displays a button for undo.

The active application may also add its own buttons to the toolbar. To do so, respond to the menuCmdBarOpenEvent and use MenuCmdBarAddButton to add the button. Listing 4.1 shows some code from the Memo application that adds to the command toolbar a button that displays the security dialog and then prevents the field manager from adding other buttons.

Listing 4.1  Responding to menuCmdBarOpenEvent


else if (event->eType == menuCmdBarOpenEvent) { 
  
   MenuCmdBarAddButton(menuCmdBarOnLeft,  
      BarSecureBitmap, menuCmdBarResultMenuItem,  
      ListOptionsSecurityCmd, 0);