Jul 98 Getting Started
Volume Number: 14
Issue Number: 7
Column Tag: Getting Started
Using The List Manager
by Dave Mark and Dan Parks Sydow
Before we get into this month's column, I would like to take a moment to introduce my
friend and collaborator, Dan Sydow. You might know Dan from his many Mac
programming books. Over the coming months, Dan and I will work together to produce
the monthly Getting Started column. I think Dan will help broaden the perspective of
the column. I hope you enjoy this collaboration as much as we do!
--Dave Mark
How a Mac program handles lists
In recent columns, you've learned the very basics of Mac programming, including how
to write event-based applications that make use of windows. Last month we moved
beyond the basics to look at dialog filters. Now it's time to continue on the path of
covering slightly more involved topics. This month we study the list. Including a list in
a window is a common practice in Mac programs. The list is a powerful tool that allows
the user to easily make his or her wishes known to the program. And while
implementing a list is a little more complex than, say, adding a button to a dialog box,
in this column you'll see that the List Manager provides a big assist.
The List Manager
The List Manager is the part of the Macintosh Toolbox that allows you to create and
manage scrollable lists. Such a list allows users to select an item from a group of
items. The vast majority of Macintosh applications make use of the List Manager,
albeit indirectly. The standard Open dialog box common to programs that allow the user
to choose a file to open holds a list created and governed by the List Manager. Figure 1
shows the result of a call to the Toolbox function StandardGetFile().
Figure 1. The List Manager, as used by StandardGetFile().
The dialog box shown in Figure 1 is the product of calls to List Manager functions
that display the list of files to open, and Dialog Manager functions that create the dialog
box that houses the list. StandardGetFile() shields all these calls from you, the
programmer. In this article we'll dig a little deeper and see how to make use of the List
Manager directly to place a list in a window of our own creation.
PictLister
This month's program is PictLister -- a program designed to showcase the List
Manager. PictLister lets you create a window listing all the PICT resources available
to your program. The available resources include those in the application's own
resource fork, as well as those present in any resource files that the System has open.
An example of the latter is the System file's own resource fork, which is always open
and accessible by applications. The window on the left side of Figure 2 includes a list
that shows the PICT resources found by my copy of PictLister.
Figure 2. A PictLister window.
To demonstrate how user-interaction with a list takes place, double-clicking on the
name of a PICT resource causes PictLister to display the selected picture in its own
window. Figure 2 shows the picture-displaying window that appears when the Party
Hats item is selected in from the list in the Picture List window.
Creating the PictLister Resources
Start by creating a folder named PictLister inside your development folder. Fire up
ResEdit and create a file named PictLister.rsrc inside your PictLister folder.
PictLister needs one menu bar resource and three menu resources in order to display
its menu bar. Begin by creating an MBAR resource with an ID of 128. The MBAR
should list three MENU resource IDs: 128, 129, and 130. Create three MENU
resources according to the specifications in Figure 3. Be sure to include a separator
line as the third item in the File menu.
Figure 3. The three MENU resources.
You'll need to create two WIND resources. The first WIND has an ID of 128, and defines
the properties of the list window. Create this WIND based on the specifications shown
in Figure 4. Note that the Close box check box is unchecked. Because the list window
is the heart of the PictLister program, it doesn't include a close box -- it remains on
screen until the user quits.
Figure 4. The list window WIND resource.
Any time a picture is displayed in PictLister, it's displayed in the same window -- a
window based on a WIND resource with an ID of 129. The picture window won't be
resizable, so after you create this WIND, click on the icon second from the left in the
row of small window icons located at the top of the WIND (it doesn't include a size
box). The picture window is closeable, so check the Close box check box. Set the
location and size of the window to any reasonable values -- PictLister will be resizing
the window as the program runs.
Now add any number of PICT resources to the resource file. Go into the scrapbook (or
your favorite graphics application) and use Copy and Paste to create a series of PICT
resources in the resource file. When finished, double-click on the icon labeled PICT in
the PictLister.rsrc file to open a window that displays each picture. One-by-one, click
on a PICT resource, select Get Resource Info from the Resource menu, type in a name,
and check the Purgeable check box. That last step gives the system to free up the
memory the picture occupies when the picture data has been loaded but isn't in use.
Figure 5 shows the Get Resource Info window for my first PICT resource.
Figure 5. Get Resource Info for my first PICT resource.
It's important to name your PICT resources, since PictLister uses the PICT's name to
represent the PICT in a PictLister window (refer back to Figure 2 to see an
example).
Creating the PictLister Project
If you haven't saved the resource file and quit ResEdit, do so now. Launch CodeWarrior
and create a new project based on the MacOS:C_C++:MacOS Toolbox:MacOS Toolbox
68Kstationary. Uncheck the Create Folder check box. Name the project PictLister.mcp
and place it in your PictLister folder. Remove SillyBalls.c and SillyBalls.rsrc from
the project; we will not be using these files in this project. From the Finder, drag and
drop your PictLister.rsrc file into the project window. Click the OK button if you see
the Add Files dialog box. Our project won't be using any of the standard ANSI libraries,
so you can remove a little clutter by dragging the ANSI Libraries folder from the
project window to your desktop's Trash can.
Choose New from the File menu to create a new source code window. Save it with the
name PictLister.c, then select Add Window from the Project menu to add this new file
to your project. Now your project window should look similar to mine -- the one
pictured in Figure 6.
Figure 6. PictLister project window.
Now it's time to type in the PictLister code in the PictLister.c file. You can do as you
read the through the following source code walk-through, or you can greatly reduce
your efforts by downloading the whole project from MacTech's ftp site
ftp://ftp.mactech.com/src/.
Walking Through the Source Code
PictLister makes use of code that's been discussed in recent columns, so our
explanation of things like the event loop and window creation is light. Instead, the focus
is on list-related code.
PictLister starts off with a bunch of #defines, some familiar, some not. As usual,
you'll see what they do in context.
/********************* constants *********************/
#define kSleep 7
#define kMoveToFront (WindowPtr)-1L
#define kListDefProc 0
#define kDrawIt true
#define kHasGrow true
#define kHasHScroll true
#define kHasVScroll true
#define kFindNext true
#define kMinWindWidth 150
#define kMinWindHeight 60
#define kWindOrigWidth 200
#define kWindOrigHeight 255
#define kBaseResID 128
#define kListWindID kBaseResID
#define kPictureWindID kBaseResID+1
#define mApple kBaseResID
#define iAbout 1
#define mFile kBaseResID+1
#define iQuit 1
The global variable gDone serves its usual role, indicating when it's time to drop out of
the main event loop. There will be just one list window open at all times, so it makes
sense to declare the global WindowPtr variable gListWindow to keep track of it. The
ListHandle variable gListHandle makes it easy to access the list window's list at any
time. A similar situation exists for the picture window: gPictWindow lets us access the
picture window, while gCurrentPicture provides a means of working with the
window's picture.
/********************** globals **********************/
Boolean gDone;
WindowPtr gListWindow = NULL;
ListHandle gListHandle = NULL;
WindowPtr gPictWindow = NULL;
PicHandle gCurrentPicture = NULL;
As usual, we provide a function prototype for each function in the source file.
/********************* functions *********************/
void ToolBoxInit( void );
void MenuBarInit( void );
void CreatePictureWindow( void );
void CreateListWindow( void );
void EventLoop( void );
void DoEvent( EventRecord *eventPtr );
void HandleMouseDown( EventRecord *eventPtr );
void DoContentClick( EventRecord *eventPtr,
WindowPtr window );
void SetWindowPicture( void );
void DoGrow( EventRecord *eventPtr, WindowPtr window );
void DoUpdate( EventRecord *eventPtr );
void DoActivate( WindowPtr window, Boolean becomingActive );
void HandleMenuChoice( long menuChoice );
void HandleAppleChoice( short item );
void HandleFileChoice( short item );
The main() routine initializes the Toolbox, sets up the menu bar, opens a couple of
windows, then enters the main event loop.
/************************ main ***********************/
void main( void )
{
ToolBoxInit();
MenuBarInit();
CreatePictureWindow();
CreateListWindow();
EventLoop();
}