TweetFollow Us on Twitter

May 99 Getting Started

Volume Number: 15 (1999)
Issue Number: 5
Column Tag: Getting Started

Resource Files

by Dan Parks Sydow

How a Mac program accesses resources stored in external files

Understanding what resources are, and how to work with them, is critical to programming the Mac. After even only the briefest introduction to Macintosh programming, it becomes obvious to a programmer that it's resources that define the interface of a Mac program. But resources can be used for much more than defining the look of a program's menus, windows, and dialog boxes. A resource can be used to store a sound, a few (or a few thousand) characters of stylized text, a program preference (such as the screen placement of a window), or just about any other type of information a clever developer can think of.

The resources that define a program's interface are invariably stored within the application itself - within the program's resource fork. But a resource doesn't have to be a part of a program in order to be used by that program. Instead, a resource can reside in a separate resource file that the program opens and accesses. In this article we take a look at why resources might be stored in a file external to a program, and how a program accesses the resources in such a file. In next month's Getting Started we'll expand on this month's techniques in order to develop a program that creates, maintains, and uses, its own preferences file.

Resource Forks

The contents of a Macintosh file are said to exist in forks. There are two types of file forks - the resource fork and the data fork. A Macintosh file can consist of either or both types of forks (some will say that a file always consists of both forks, though one fork may just happen to be empty). As you'd expect, the resource fork holds resources. The data fork holds other types of information. Exactly what type of information is in a file's data fork is dependent on the program that created the file. If you save a SimpleText document, for instance, the resulting file will have a data fork that holds the text of the saved document. You can see how much information is stored in both forks of any one file by opening that file in ResEdit and choosing Get Info from the File menu. Figure 1 shows that a small SimpleText text file named READ ME has 356 bytes in its resource fork and 4092 bytes in its data fork. Without a program like ResEdit, you wouldn't know the exact byte values of the file's forks. But the general result should be as you'd expect - a text file stores the file's characters in the data fork, and has little need for resources (in this case SimpleText stores a resource that keeps track of any stylized text that appears in the READ ME file).

Figure 1. Using ResEdit to find the size of a file's forks.

When viewed in a hex editor (a type of text editor that displays a file's contents in hexadecimal format), the information in either fork appears to be simply a stream of hexadecimal characters. Consider ResFiles, this month's example program. When a PowerPC version of ResFiles is built, the Metrowerks linker merges the compiled program code with the project resources. The result is a program that holds the compiled code in its data fork and resources in its resource fork. In Figure 2 a special hex editor named BrainHex (shareware available for downloading at <>) is displaying the hex content of both forks.

Figure 2. Using a hex editor to view the contents of both forks of a file.

In the sense that both forks hold a series of hex characters, the contents of the two forks look similar. But there are differences. Those differences involve formatting - the way in which special formatting characters appear throughout information in the fork. When a program opens a file of its own creation, the program knows how to read in the information from the file's data fork - and it knows how to format that information. When a word processor opens one of its files, it knows which words should be displayed in boldface, the font to use for each section of text, and so forth. When a graphics program opens one of its files, it knows how to interpret the data fork information and display the proper shapes in the appropriate colors, patterns, and so on. Thus no single program can open and make use of the data fork of all types of files - no one program knows how to format the data stored in every type of file. For a file's resource fork, this isn't the case - there is a single program that can make sense of the contents.

The information that makes up a resource follows a clearly defined format. A developer who knows that format can write an editor that can open and display (in a meaningful way) that resource. Regardless of the type of file the resource resides in (the resource fork of an application, a word processor file, a graphics file, and so forth), the resource editor can make sense of that resource. Apple has created such a program - ResEdit. Apple isn't the only company that's created a resource editor, though. Most notable of the third-party resource editors is the very useful Resorcerer by Mathemaesthetics, Inc. (<>).

Applications and Resource Files

When a program reads information from a file - whether the information is a resource or some other type of data - the operation is a relatively safe one. When an error does occur, it more typically occurs when a program writes information to a file. If a write operation fails, the result can be a corrupt file. A program is safe in storing its interface-related resources in its own resource fork because the program typically reads the resources from this fork, but seldom or never writes to this fork. When a program opens a window, it may do so be reading WIND resource information into memory. When a program displays a menu bar and menus, it may do so be reading MBAR and MENU resources. In both cases no resource fork information is altered. If a program is to work with resources that it may in fact alter, it is safer to store these resources in a different resource fork. That is, these resources should be kept in the resource fork of a separate file. Corruption of a file is always bad news, but if the writing of a resource corrupts an external file, the damage is less costly than if the writing of the resource corrupts the application itself.

A preferences file is a good example of the use of storing resources external to an application. A preferences file doesn't have to be a resource file (software developers can devise any number of schemes for storing user-configurable options in a file), but it often is. The information in a preferences file can be altered by a program any time the user specifies that some application setting should be changed (often be choices made in a Preferences dialog box accessed through a Preferences item in the program's Edit menu). If the changing of some information in a preferences file corrupts that file, the application is not damaged. If a subsequent attempt to access the preferences file fails, the application typically creates a new preferences file that holds some default settings. The user will need to re-enter his or her preferences, but that's a small price to pay to preserve the integrity of the application.

Avoiding application corruption is one reason to keep a resource in an external file. Other reasons for storing resources outside of an application involve portability and application updating. For example, a program that plays sounds may store those sounds as sound resources in external resource files (refer to Getting Started in this year's February issue of MacTech for the details of sound resource playing). To allow the program to play more, or new, sounds, the user might then need to obtain only the sound files. The user won't have to get a new copy of the entire application and then reinstall the program (which would be the case if the sounds were all stored within the application's resource fork). Carrying on with our sound playing program example, imagine that the application allowed users to supply their own sounds. It's an easy task to get sounds that are stored as resources: one can create, download, buy, or swap files with others. So here again the user benefits - he or she can obtain sounds and make use of them without having to obtain a new version of the sound playing program.

Toggling Resource Forks

Before jumping into the specifics of working with resource files, a little resource-related terminology is in order. When most or all of a file's information is held in the file's resource fork, that file is often referred to as a resource file. When that file's resource fork is being manipulated (opened, written to, read from, or closed) by a program, programmers often refer to the fork itself as a file. When you hear about a Toolbox routine being used to "open the resource file," that routine is in fact opening the resource fork of the file. So in your readings of resource-related material, you'll occasionally encounter the terms resource fork and resource file used interchangeably. In this introductory article we'll make a special effort to stick with fork when discussing the fork and file when discussing the file that owns the fork - but be aware that a looseness of this terminology does exist. Here we'll also talk about an external resource file. Of course any file is external to a program, but for clarity we'll put an emphasis on external. That should help avoid confusion with a project resource file, the contents of which become internal to an application and thus a part of an application's internal resource fork.

When a program executes, its own resource fork is open - by default it's available for reading from and writing to. This same program can open the resource forks from any number of other files as well. When a program opens a resource fork (including its own), the File Manager assigns a reference number to it. This reference number is then used by the application to make one (and only one) resource fork the current fork. Having only one resource fork considered the current fork prevents the application from loading a wrong resource into memory. Keep in mind that different files can hold similarly numbered resources. For instance, two files could each hold a WIND resource with an ID of 128. If a call to GetNewWindow() specified that a WIND with an ID of 128 be used as the basis for the new window, and the resource forks of both of these files were open, the program could load the wrong resource. Specifying which fork to use before calling GetNewWindow() solves this problem.

The Toolbox routine CurResFile() returns the reference number of the resource fork that's considered current. When an application launches we know that the application's resource fork is automatically opened and made current. If an application will be opening other resource forks, it's a good idea to retrieve and save the reference number of the application resource fork just after application start-up:

short      gApplRsrcForkRef;

gApplRsrcForkRef = CurResFile();

When the application opens the resource fork of a different resource file, the reference number of the newly opened file will be returned to the program. At that time the program should store this reference number as well. Then, at any time in the execution of the program either resource fork can be made current by calling the Toolbox function UseResFile(). The only parameter to this routine is the reference number of the file to make current. This more involved (but still incomplete) snippet provides an example:

short      gApplRsrcForkRef;
short      gFileRsrcForkRef;

gApplRsrcForkRef = CurResFile();

[ Here we'd open the resource fork of a resource file ]
[ and save its reference number in gFileRsrcForkRef ]

UseResFile( gFileRsrcForkRef );

[ Now resource-related tasks, such as calls to  ]
[ GetNewWindow(), GetPicture(), and GetResource(), ]
[ use resources from the external resource file ]

UseResFile( gApplRsrcForkRef );

[ Now resource-related tasks use resources from the ]
[ application resource fork       ]

Opening and Closing a Resource Fork

The previous snippet left out an important detail - exactly how a program goes about opening the resource fork of a file. This task is accomplished by calling the Toolbox routine FSpOpenResFile(). The routine name's leading FSp indicates that the function is one that works with a file system specification - a variable of type FSSpec. An FSSpec for a file can be obtained by calling the Toolbox function FSMakeFSSpec(). This function requires four parameters. Together, the first and second parameters define where on disk the file named in the third parameter is located. The fourth parameter is the file system specification, and is filled in by FSMakeFSSpec(). Consider this snippet:

#define   kRsrcFileName   "\pMyResourceFile"

short      volRef = 0;
long       dirID = 0;
FSSpec     rsrcFSSpec;
FSMakeFSSpec( volRef, dirID, kRsrcFileName, &rsrcFSSpec );

The first parameter is the reference number for the volume that holds the file in question. Every volume, or drive, connected to the user's machine has a unique volume reference number. The second parameter is an ID for the directory that holds the file. Every directory, or folder, on a drive has a unique directory ID. The third parameter is the file's name. To reference any one file, only these three pieces of information (volume reference number, directory ID, and file name) are ever needed. From this information a FSSpec can always be created.

If a file is located in the same folder as the application that's accessing the file, then a value of 0 can be used in place of both the volume reference number and the directory ID. For simplicity, that's what we've done in the above example. Plugging in a zero for the first two parameters is a simple means of getting an FSSpec for a file, but it also means that the file must be stored in the same folder as the application or the returned FSSpec will be invalid. In a future Getting Started article we'll explore more fully the topic of working with files - including how a program accesses files in other directories and on other disks.

Once the program has the FSSpec of a file, a call to the Toolbox function FSpOpenResFile() is made to open the resource fork of the file. The first of two FSpOpenResFile() parameters is the just-obtained FSSpec. The second parameter is a file permission constant. Using the Apple-defined fsRdPerm allows the application to read from (load resources from) the opened fork, but denies the application the ability to write to (alter resources in) the fork. To give an application the power to both read from and write to a resource fork, instead use fsRdWrPerm as the permission constant:

gFileRsrcForkRef = FSpOpenResFile( &rsrcFSSpec, fsRdWrPerm );

With all the pieces to the fork-opening puzzle in place, we can go back and rewrite the earlier snippet - the one that omitted the details of opening the resource fork. This final snippet opens the resource fork of a file named MyResourceFile and then opens a window based on WIND resource 128 from MyResourceFile. The code then goes on to open a second window. This second window is also based on a WIND with an ID of 128 - but this second window uses a WIND resource from the application's resource fork.

#define   kRsrcFileName   "\pMyResourceFile"

short      gApplRsrcForkRef;
short      gFileRsrcForkRef;

short      volRef = 0;
long         dirID = 0;
FSSpec      rsrcFSSpec;

gApplRsrcForkRef = CurResFile();

FSMakeFSSpec( volRef, dirID, kRsrcFileName, &rsrcFSSpec );
gFileRsrcForkRef = FSpOpenResFile( &rsrcFSSpec, fsRdWrPerm );

UseResFile( gFileRsrcForkRef );

UseResFile( gApplRsrcForkRef );

CloseResFile( gFileRsrcForkRef );

The above snippet ends with a call to CloseResFile() - the Toolbox function that closes an open resource fork. CloseResFile() is called only to close the resource fork of an external file - the application's resource fork remains open as long as the application is running. Also note that if a program will be using the resources in an external file frequently, that file's resource fork can be left open for the duration of a program's running. When the program exits there's then no need to call CloseResFile() - the program automatically closes all open resource forks (including its own) when the program terminates.


This month's program is called ResFiles. Running ResFiles results in the appearance of the menu bar and window shown in Figure 3. The one menu of interest is shown - the Picture menu holds an item named Display All Pictures. When ResFiles launches, an empty window opens. Choosing the Display All Pictures item results in ResFiles opening the resource fork of an external resource file and then displaying one after another every picture that's stored in that file. In this example the external file (named MyResourceFile) holds five PICT resources - each displaying one of the different "flavors" of the iMac computer. The number of pictures in MyResourceFile, and the pictures themselves, can be changed and the Display All Pictures item will still work correctly.

Figure 3. The ResFiles menu bar and window.

Creating the ResFiles Resources

The project begins with the creation of a new folder named ResFiles in your CodeWarrior development folder. Launch ResEdit and create a new resource file named ResFiles.rsrc, making sure to designate the ResFiles folder as the resource file's destination. Figure 4 shows the five types of resources that go into the ResFiles.rsrc file.

Figure 4. The ResFiles resources.

The one ALRT and one DITL resource used by ResFiles are standard to Getting Started - they're used in the display of an error-handling alert posted by the DoError() routine that's a part of each column's example program. The one WIND resource is used in the creation of the program's picture-displaying window. The exact placement and size of the window isn't critical, but it should be large enough to hold whatever pictures will eventually be displayed in it. Figure 4 shows the four MENU resources that the ResFiles program uses. After creating the MENU resources, create a single MBAR resource that references the ID of each of the four menus. That completes the ResFiles.rsrc file. Don't quit ResEdit just yet, though.

Now you need to create a second resource file. This file won't become a part of the project, but will instead serve as the external file that the ResFiles program accesses. Choose New from the ResEdit File menu, then make sure the file will end up in the ResFiles folder - the same folder that holds the project resource file ResFiles.rsrc. Give the file the name MyResourceFile (that's the name the ResFiles code will be expecting to see). Now draw or find a few pictures and paste them into this resource file. The number of pictures you paste into this file isn't critical - the ResFiles code is written to accommodate any number of PICTs. The ResFiles code doesn't adjust the size of the picture-displaying window though, so you'll want to keep the size of the pictures in line with the size of the window defined in the WIND resource in the ResFiles.rsrc file. Figure 5 shows that MyResourceFile consists of nothing more than a number of PICT files. After saving both files, quit ResEdit. You're now ready to create the ResFiles project.

Figure 5. The MyResourceFile resources.

Creating the ResFiles Project

Start up CodeWarrior and choose New Project from the File menu. Base the new project on the MacOS:C_C++:MacOS Toolbox:MacOS Toolbox Multi-Target project stationary. Uncheck the Create Folder check box before clicking the OK button. Give the project the name ResFiles.mcp, and make sure the ResFiles folder will be the project's destination.

Add the ResFiles.rsrc file to the new project and then remove the SillyBalls.rsrc file. No standard ANSI libraries are used by the project, so you can optionally remove the ANSI Libraries folder from the project window. Don't add the second resource file - the one you've named MyResourceFile. The ResFiles program will eventually use this file - the file won't become a part of the program.

Now choose New from the File menu to create a new, empty source code window. Save the new file, giving it the name ResFiles.c. Choose Add Window from the Project menu to add this file to the project. Next, remove the SillyBalls.c placeholder file from the project window. Now you're all set to type in the source code.

If you want to save some work, you can skip all the above steps_ and instead download the entire ResFiles project (including the resource file MyResourceFile) from MacTech's ftp site at <>.

Walking Through the Source Code

ResFiles starts with the standard list of constant definitions, most of which define resource IDs. One exception is kRsrcFileName, which defines the name of the external file that holds the picture resources that ResFiles will make use of.

/********************* constants *********************/

#define      kWINDResID        128
#define      kMBARResID        128
#define      kALRTResID        128
#define      kPICTiMacID       128
#define      kRsrcFileName     "\pMyResourceFile"

#define      kSleep            7
#define      kMoveToFront      (WindowPtr)-1L

#define      mApple            128
#define      iAbout            1

#define      mFile             129
#define      iQuit             1

#define      mPicture          131
#define      iDisplayPicts     1

ResFiles declares three global variables. The Boolean flag gDone tells the program that it's time to quit. The two short variables, gApplRsrcForkRef and gFileRsrcForkRef, are used to hold the reference number of the application's resource fork and the reference number of the resource fork of the external resource file that ResFiles opens. gFileRsrcForkRef is set to 0 - this is a part of the program's simple scheme of keeping track of whether an external resource fork is currently open. A gFileRsrcForkRef value of 0 indicates that no external resource fork is initially open.

/****************** global variables *****************/

Boolean      gDone;
short        gApplRsrcForkRef;
short        gFileRsrcForkRef = 0;

Next come the program's function prototypes.

/********************* functions *********************/

void      ToolBoxInit( void );
void      MenuBarInit( void );
void      InitWindow( void );
void      OpenResourceFork( void );
void      CloseResourceFork( void );
void      DrawOnePicture( short );
void      DrawAllPictures( void );
void      EventLoop( void );
void      DoEvent( EventRecord *eventPtr );
void      HandleMouseDown( EventRecord *eventPtr );
void      HandleMenuChoice( long menuChoice );
void      HandleAppleChoice( short item );
void      HandleFileChoice( short item );
void      HandlePictureChoice( short item );
void      DoError( Str255 errorString );

The main() function begins by initializing the Toolbox and the menu bar. Because the launching of a program automatically opens the program's resource fork and makes that fork current, and because ResFiles hasn't explicitly opened the resource fork of an external resource file yet, we know that the application resource fork is now the current resource fork. So we also know we're justified in calling CurResFile() to take hold of the reference number of the application resource fork for later use by the program. After that an empty window is opened (for the eventual display of pictures), and the program goes into an event loop.

void   main( void )

   gApplRsrcForkRef = CurResFile();


ToolBoxInit() and MenuBarInit() are the same as prior versions.

/******************** ToolBoxInit ********************/

void      ToolBoxInit( void )
   InitGraf( &qd.thePort );
   InitDialogs( nil );

/******************** MenuBarInit ********************/

void      MenuBarInit( void )
   Handle          menuBar;
   MenuHandle      menu;
   menuBar = GetNewMBar( kMBARResID );
   SetMenuBar( menuBar );
   menu = GetMenuHandle( mApple );
   AppendResMenu( menu, 'DRVR' );

InitWindow() consists of some very basic code that opens a window. The resource fork of the external file hasn't been opened yet, so ResFiles looks to the application resource fork for the WIND resource specified in the call to GetNewWindow(). As an added precaution, a call to UseResFile() with an argument of gApplRsrcForkRef could precede the call to GetNewWindow(). Such a use of UseResFile() might be overkill here, but it could be practical in a large program where it is harder to keep track of just when external resource forks are open.

/******************** InitWindow *********************/

void      InitWindow( void )
   WindowPtr   window;
   window = GetNewWindow( kWINDResID, nil, (WindowPtr)-1L );
   ShowWindow( window );
   SetPort( window );

When the user chooses Display All Pictures from the Picture menu, the application-defined function DrawAllPictures() is invoked. This function begins by invoking the program's OpenResourceFork() function to open the resource fork of the picture-holding external resource file. OpenResourceFork() is discussed ahead, though by now you can guess that its code relies on calls to FSMakeFSSpec() to create an FSSpec for the resource file and FSpOpenResFile() to then open the file's resource fork. After opening the resource fork, DrawAllPictures() enters a loop that draws one picture at each pass through the loop. The Toolbox function Count1Resources() returns the number of resources of a particular type in the current resource fork. After all the resource file's pictures have been drawn, the application-defined function CloseResourceFork() (discussed ahead) is invoked to close the fork.

/****************** DrawAllPictures ******************/

void      DrawAllPictures( void )
   short      i;
   short      numPicts;
   short      pictID = kPICTiMacID;

   numPicts = Count1Resources( 'PICT' );

   for ( i = 0; i < numPicts; i++ )
      DrawOnePicture( pictID );


Pass DrawOnePicture() the resource ID of a PICT resource and the function loads that resource's picture data into memory and draws the picture. The picFrame field of a picture holds the boundaries of the picture. After ensuring that the boundaries have an origin of (0, 0), a call to the Toolbox function DrawPicture() does the work of drawing the picture. A call to the Toolbox function Delay() creates a delay of a second and a half (the first parameter being the number of sixtieths of a second to pause). The second Delay() parameter gets filled with the length of time the user's Mac has been on, in sixtieth seconds (a value you'll almost always ignore). Without a delay the picture would be overwritten almost immediately by the next picture (because DrawOnePicture() is being called from within a loop in the DrawAllPictures() routine).

/****************** DrawOnePicture *******************/

void   DrawOnePicture( short pictID )
   PicHandle       picture;
   Rect            r;
   short           width;
   short           height;
   unsigned long   theLong;

   picture = GetPicture( pictID );
   if ( picture == nil )
      DoError( "\pLoading picture failed" );
   r = (**picture).picFrame;
   width = r.right - r.left;
   height = r.bottom -;
   SetRect( &r, 0, 0, width, height );

   DrawPicture( picture, &r ); 

   Delay( 90, &theLong );

   EraseRect( &r );
   ReleaseResource( (Handle)picture );

OpenResourceFork() requires little explanation - almost all of its code was introduced earlier in this article. The only new twist is the call to the Toolbox function ResError(). After calling a Resource Manager function, you can call ResError() in order to determine whether a resource-related error occurred. ResError() checks the value that's kept in the ResErr system global variable and returns an OSErr value that describes the type of error that occurred. If there was no error, ResError() returns a value of noErr. The More Macintosh Toolbox volume of Inside Macintosh provides more information on FSpOpenResFile() and error values returned by ResError().

/***************** OpenResourceFork ******************/

void      OpenResourceFork( void )
   short      volRef = 0;
   long       dirID = 0;
   FSSpec     rsrcFSSpec;
   OSErr      err;

   FSMakeFSSpec( volRef, dirID, kRsrcFileName, &rsrcFSSpec );

   gFileRsrcForkRef = FSpOpenResFile( &rsrcFSSpec, fsRdPerm );
   err = ResError();
   if ( err != noErr )
      DoError( "\pOpening resource file failed" );

   UseResFile( gFileRsrcForkRef ); 

To close the external resource fork, ResFiles calls the application-defined CloseResourceFork() function. This short routine relies on the Toolbox function CloseResFile() to close the fork. After that, gFileRsrcForkRef is set to 0 to indicate that no external resource fork is open. Recall that when gFileRsrcForkRef was declared, it was assigned a value of 0. If our program ever needs to check to see if an external resource fork is open, it can take a look at the value of gFileRsrcForkRef. If this global variable has a value of 0, an external fork isn't open. If gFileRsrcForkRef has any value other than 0, the program knows an external resource fork is open. Before exiting, CloseResourceFork() calls UseResFile() to ensure that the application's resource fork is now the current application fork.

/**************** CloseResourceFork ******************/

void   CloseResourceFork( void )
   CloseResFile( gFileRsrcForkRef );
   gFileRsrcForkRef = 0;
   UseResFile( gApplRsrcForkRef );

The remainder of the ResFiles code is the event-handling code with which you should be familiar - it's included in all of our Getting Started programs.

/********************** EventLoop ********************/

void      EventLoop( void )
   EventRecord      event;
   gDone = false;
   while ( gDone == false )
      if ( WaitNextEvent( everyEvent, &event, kSleep, nil ) )
         DoEvent( &event );

/*********************** DoEvent *********************/

void      DoEvent( EventRecord *eventPtr )
   char   theChar;
   switch ( eventPtr->what )
      case mouseDown: 
         HandleMouseDown( eventPtr );
      case keyDown:
      case autoKey:
         theChar = eventPtr->message & charCodeMask;
         if ( (eventPtr->modifiers & cmdKey) != 0 ) 
            HandleMenuChoice( MenuKey( theChar ) );
      case updateEvt:
         BeginUpdate( (WindowPtr)(eventPtr->message) );
         EndUpdate( (WindowPtr)(eventPtr->message) );

/******************* HandleMouseDown *****************/

void      HandleMouseDown( EventRecord *eventPtr )
   WindowPtr   window;
   short       thePart;
   long        menuChoice;
   thePart = FindWindow( eventPtr->where, &window );
   switch ( thePart )
      case inMenuBar:
         menuChoice = MenuSelect( eventPtr->where );
         HandleMenuChoice( menuChoice );
      case inSysWindow : 
         SystemClick( eventPtr, window );

/******************* HandleMenuChoice ****************/

void      HandleMenuChoice( long menuChoice )
   short   menu;
   short   item;
   if ( menuChoice != 0 )
      menu = HiWord( menuChoice );
      item = LoWord( menuChoice );
      switch ( menu )
         case mApple:
            HandleAppleChoice( item );
         case mFile:
            HandleFileChoice( item );
         case mPicture:
            HandlePictureChoice( item );
      HiliteMenu( 0 );

/****************** HandleAppleChoice ****************/

void      HandleAppleChoice( short item )
   MenuHandle      appleMenu;
   Str255          accName;
   short           accNumber;
   switch ( item )
      case iAbout:
         SysBeep( 10 );
         appleMenu = GetMenuHandle( mApple );
         GetMenuItemText( appleMenu, item, accName );
         accNumber = OpenDeskAcc( accName );

/******************* HandleFileChoice ****************/

void      HandleFileChoice( short item )
   switch ( item )
      case iQuit:
         gDone = true;

When the user chooses Display All Pictures from the Picture menu, HandlePictureChoice() gets called. HandlePictureChoice() then invokes DrawAllPictures() to open the external resource file and display all of its pictures in the program's window.

/***************** HandlePictureChoice ***************/

void      HandlePictureChoice( short item )
   switch ( item )
      case iDisplayPicts:

/*********************** DoError *********************/

void      DoError( Str255 errorString )
   ParamText( errorString, "\p", "\p", "\p" );
   StopAlert( kALRTResID, nil );

Running ResFiles

Run ResFiles by selecting Run from CodeWarrior's Project menu. After compiling the code and building a program, CodeWarrior runs the program. The menu bar and a small empty window appear. Choose Display All Pictures from the Picture menu to display each of the PICT resources that are a part of the MyResourceFile resource file. Note that if you move this resource file out of the application's folder, the program will invoke it's DoError() routine and quit. Go ahead and try forcing that error to verify that DoError() does its work!

The program can be changed without doing any of the following: altering source code, recompiling, or making changes to the program's resources. To see how that's accomplished, launch ResEdit and open the MyResourceFile resource file. Remove or add any number of pictures. The only requirement is that the PICT resource IDs are numbered sequentially starting with a value of 128. Then save and close the file. Now again run ResFiles (if ResFiles was already running, that's fine too). Choose Display All Pictures from the Picture menu and the program will successfully display all of the pictures in MyResourceFile - regardless of the changes you made.

Till Next Month...

Will the use of an external resource file benefit your own Mac program? The need for an external file may not be readily apparent, but indeed your program can make use of at least one such file. A program's preferences file is often nothing more than a resource file. Now that you've read a primer on resource files, you're part of the way to giving your own program the ability to store preferences. Next month you'll go the rest of the way to that end. In next month's Getting Started column we'll carry on with resource files, with the emphasis on describing how a program creates a resource file on the fly and then writes resources to, and reads resources from, that file. Until next month you can dig deeper into resources by reading the Resource Manager chapter of the More Macintosh Toolbox volume of Inside Macintosh...


Community Search:
MacTech Search:

Software Updates via MacUpdate

Google Chrome 59.0.3071.109 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
Chromium 59.0.3071.109 - Fast and stable...
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web. Version 59.0.3071.109: This update has no Flash plug-... Read more
iShowU Instant 1.1.8 - Full-featured scr...
iShowU Instant gives you real-time screen recording like you've never seen before! It is the fastest, most feature-filled real-time screen capture tool from shinywhitebox yet. All of the features you... Read more
MacFamilyTree 8.2 - Create and explore y...
MacFamilyTree gives genealogy a facelift: modern, interactive, convenient and fast. Explore your family tree and your family history in a way generations of chroniclers before you would have loved.... Read more
DiskCatalogMaker 7.0.2 - Catalog your di...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
ExpanDrive 5.5.4 - Access cloud storage...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
Together 3.8.6 - Store and organize all...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Features Smart storage. With simple drag-and-drop... Read more
DiskCatalogMaker 7.0.2 - Catalog your di...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
MacFamilyTree 8.2 - Create and explore y...
MacFamilyTree gives genealogy a facelift: modern, interactive, convenient and fast. Explore your family tree and your family history in a way generations of chroniclers before you would have loved.... Read more
iShowU Instant 1.1.8 - Full-featured scr...
iShowU Instant gives you real-time screen recording like you've never seen before! It is the fastest, most feature-filled real-time screen capture tool from shinywhitebox yet. All of the features you... Read more

Latest Forum Discussions

See All

Age of Rivals (Games)
Age of Rivals 3.3 Device: iOS Universal Category: Games Price: $.99, Version: 3.3 (iTunes) Description: Deep civilization-building strategy in a fast-paced card game! | Read more »
Panthera Frontier (Games)
Panthera Frontier 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: | Read more »
Angry Birds Evolution beginner's gu...
Angry Birds changes things up a fair bit in its latest iteration, Angry Birds Evolution. The familiar sling-shot physics mechanics are still there, but the game now features team-based gameplay, RPG elements, and a new top-down view. With all of... | Read more »
Sega Forever is for the retro game fans
Sega is launching a new retro games service titled Sega Forever, in a move that's sure to delight games enthusiasts with a bit of nostalgia. Sega's releasing five classic games for free. The titles include Sonic the Hedgehog, Phantasy Star II,... | Read more »
The Little Acre (Games)
The Little Acre 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: | Read more »
Lovely adventure game 'The Little A...
The Little Acre makes its way from PC to iOS today and it's a real charmer. It's a lovely little adventure game set in 1950's Ireland, gorgeously animated in a style slightly reminiscent of old Disney films. The game won a lot of praise for its... | Read more »
Futurama: Worlds of Tomorrow officially...
Futurama: Worlds of Tomorrow arrives next Thursday, and it features . . . Stephen Hawking? Turns out a few of your favorite science super stars, including Bill Nye, Neil DeGrasse Tyson, and George Takei will be making an appearance alongside the... | Read more »
MU Origin’s new update offers exciting c...
MU Origin is kicking off the summer with style. Its latest update is a real doozy, offering up plenty of fresh content. New challenges, some extra help for newcomers, and new costumes are just a few of the things you will find in the new patch. | Read more »
Pokémon GO introduces Raid Battles and a...
If you were hoping to conquer any gyms today in Pokémon GO you're in for a bit of disappointment. Niantic has closed gyms in the game to prepare for a huge upcoming update that is going to complete change Pokémon GO's competitive elements. The... | Read more »
Death Road to Canada's huge "C...
Death Road to Canada is getting a massive content update, COCCYX, later this month, Us here at 148Apps quite liked Death Road to Canada. In fact, we gave it a rare 4.5 stars. It's a deeper spoof on Oregon Trail, only this time you're heading... | Read more »

Price Scanner via

Three Off-The-Beaten-Track iOS Apps That Dese...
One of the great things about using iPads and iPhones is the vast selection of apps available for most anything you want or need to do. The three outlined in this article have been in my core app... Read more
Apple No. 1 Spot In Gartner Top 100 Vendors i...
Gartner, Inc. has unveiled the top global 100 vendors in IT in 2016 based on their revenue across IT (excluding communication services) and component market segments. In the Gartner Global Top 100:... Read more
Clearance iMacs available for up to $300 off...
B&H Photo has clearance 21″ and 27″ Apple iMacs available starting at $949, each including free shipping plus NY & NJ sales tax only: - 27″ 3.3GHz iMac 5K: $1999 $300 off original MSRP - 27″... Read more
1.4GHz Mac mini, refurbished, available for $...
The Apple Store has Apple Certified Refurbished 1.4GHz Mac minis available for $419. Apple’s one-year warranty is included, and shipping is free. Their price is $80 off MSRP, and it’s the lowest... Read more
Free Mixoo iOS Photo Editing App Gets Major U...
Button Software Technology has announced Mixoo 3.0, an important feature update to the company’s photo editor for iOS devices. Mixoo offers amazing ways to edit as well as decorate personal photo... Read more
FNable 2.0 Function Key Enabling Software Get...
Briksoftware has released FNable 2.0 With Touch Bar Support, a major new version of the function key enabling software now compatible with Touch Bar keyboards. FNable’s simplicity that allows users... Read more
Clearance 2016 12-inch Retina MacBooks, Apple...
Apple recently dropped prices on Certified Refurbished 2016 12″ Retina MacBooks, with models now available starting at $1019. Apple will include a standard one-year warranty with each MacBook, and... Read more
Clearance iPad Pros, Apple refurbished, avail...
Apple recently dropped prices on Certified Refurbished 2016 9″ and 12″ iPad Pros, with models now available starting at $469. An Apple one-year warranty is included with each model, and shipping is... Read more
13-inch 2.7GHz Retina MacBook Pro, Apple refu...
Apple has Certified Refurbished 13″ 2.7GHz/128GB Retina MacBook Pros available for $929–a recent $170 price drop. An Apple one-year warranty is included, and shipping is free: - 13″ 2.7GHz/128GB... Read more
Clearance 2016 13-inch MacBook Airs, Apple re...
Apple dropped prices recently on Certified Refurbished 2016 13″ MacBook Airs, with models now available starting at $809. An Apple one-year warranty is included with each MacBook, and shipping is... Read more

Jobs Board

Product Manager, *Apple* News - Apple Inc....
…on new product areas, many of which have great potential impact to Apple .Drives the definition of broad, complex, and high impact products for worldwide markets, Read more
Sr. Software Engineer, *Apple* Online Store...
…building high throughput, high performance, reliable, checkout & payment platform that support Apple online stores. You will be working with the latest in services Read more
Product Owner, *Apple* Communities - Apple...
…for managing and delivering a world-class community experience to Apple 's customers. Your primary responsibilities include developing internal-facing tools, Read more
*Apple* Customer Experience (ACE) Leader - A...
…management to deliver on business objectivesTraining partner store staff on Apple products, services, and merchandising guidelinesCoaching partner store staff on Read more
Pan Europe Market Development Manager %u2014...
…local artists across the region.* Building strong relationships with local Apple teams & collaborating on mutually beneficial projects.* Building strong Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.