Dialogger
Volume Number: 9
Issue Number: 4
Column Tag: Getting Started
Dialogger Part II, The Code 
Walking through a Dialogger
By Dave Mark, MacTech Magazine Regular Contributing Author
Note: Source code files accompanying article are located on MacTech CD-ROM orsource code disks.
Last month’s column was so long that we never got a chance to walk through the
source code. If you’re just entering the picture, pick up a copy of last month’s
MacTutor ... er ... MacTech and read through the Getting Started column. The column
describes the resources and source code that make up Dialogger, a program that
demonstrates the basics of working with the Dialog Manager, an important part of the
Macintosh Toolbox.
The Dialog Manager
The Dialog Manager gives you all the routines and data structures you’ll need to
implement a fully functional dialog box, like the one shown in Figure 1.
Figure 1. Dialogger’s Settings... dialog box.
Dialog boxes consist of a window and a list of dialog items. Each dialog item has an
associated Rect, specified in the dialog window’s local coordinates, which determines
where the item appears within the window. Each item is chosen from the list shown in
Figure 2. You should recognize this as the DITL item palette used in last month’s
column to create the DITL resource that described the items used in the Dialogger
Settings... dialog.
Figure 2. The DITL item palette.
The Dialogger DITL contained buttons, a check box, radio buttons, static text, and
a user item. I’ll explain those as we encounter them in the source code. The remaining
items are controls, edit text, icons, and pictures. A control is an item that can take on a
limited range of values. The classic example of a control in a dialog is the scroll bar,
which changes value as you scroll through a list. We’ll deal with scroll bars in a later
column.
An edit text item allows you to display text that the user may edit. The Dialog
Manager handles all the text editing chores for you. Pretty much all you have to do is
specify the default text in the edit text item, then retrieve and reset the text as you
choose.
Icons and pictures display ICON and PICT resources in the rectangle you specify.
These are pretty straight-forward. Once you finish this column, go read the Dialog
Manager section in Inside Macintosh, Volume I. With this example in hand, you should
be able to breeze through it.
The Dialogger Source Code
Much of the Dialogger source code will look familiar to you from earlier
programs. I’ll keep the chatter to a minimum. You’ve seen some of these constants
before. The rest I’ll explain as we get to them. One convention you should be aware of is
the i convention. Just as we did with menu items, constants that reflect a dialog item
start with the letter i.
/* 1 */
#define kBaseResID 128
#define kAboutALRTid 129
#define kDialogResID 128
#define kVisible true
#define kMoveToFront (WindowPtr)-1L
#define kNoGoAway false
#define kSleep 60L
#define kFirstRadio 3
#define kOn 1
#define kOff 0
Each time you add an item to a dialog item list, the item is given a unique number.
The OK button always gets number 1 and the Cancel button always gets number 2.
ResEdit’s DITL menu (which appears when you edit a DITL) allows you to renumber
the items in a DITL, as well as turn the display of item numbers on and off. In general,
it’s a good idea to write down (or print out) each of your DITL item id’s once you finish
your ResEdit session and you start writing your code. I usually create the item
#defines for my MENU and DITL resources right away so I won’t forget them.
/* 2 */
#define iAfghan 3
#define iElephant 4
#define iSquirrel 5
#define iShowPreview 7
#define iUserItem 8
#define kLeftMargin 5
#define kTopMargin 40
#define mApple kBaseResID
#define iAbout 1
#define mFile kBaseResID+1
#define iSettings 1
#define iQuit 3
Dialogger makes use of three globals. gDone is set to true when the program is
ready to exit. gShowPreview corresponds to the Show preview checkbox in the
Settings... dialog. It is set to true whenever the check box is checked. We could avoid the
use of a global by using the same initial setting for Show preview each time we enter
the routine that handles the dialog box. By using a global, however, the setting of the
check box survives, even after the dialog is dismissed.
/* 3 */
/************** Globals *************/
Boolean gDone, gShowPreview = true;
The same thinking holds true for gCurrentPICT. This global tells us which
picture we’re currently looking at, ensuring that the dialog’s Show preview brings up
the current picture of my pet Fred.
short gCurrentPICT = kBaseResID;
As always, here’s a complete list of function prototypes.
/* 5 */
/************** Functions *************/
void ToolBoxInit( void );
PicHandle LoadPICT( short picID );
void CreateWindow( void );
void MenuBarInit( 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 DoUpdate( EventRecord * eventPtr );
void DoDialog( void );
void FlipControl( ControlHandle control );
void DrawPreview( DialogPtr dialog, short picID );
void SwitchPICT( void );
The following two routines are part of System 7, and won’t work with outdated
versions of the operating system. Remember, you should be using System 7 - no
excuses!
The reason the trap addresses are listed in the source code (they’re usually listed
in the appropriate #include file) is that they’re not part of the current set of
#include files that come with THINK C.
/* 6 */
/* see tech note 304 */
pascal OSErr SetDialogDefaultItem(DialogPtr theDialog,
short newItem)
= { 0x303C, 0x0304, 0xAA68 };
pascal OSErr SetDialogCancelItem(DialogPtr theDialog,
short newItem)
= { 0x303C, 0x0305, 0xAA68 };
main() initializes the Toolbox, then sets up the menu bar and creates the My Pet
Fred window. Once that’s done, the main event loop is entered.
/* 7 */
/******************************** main *********/
void main( void )
{
ToolBoxInit();
MenuBarInit();
CreateWindow();
EventLoop();
}
Nothing new here...
/* 8 */
/*********************************** ToolBoxInit */
void ToolBoxInit( void )
{
InitGraf( &thePort );
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs( NULL );
InitCursor();
}
LoadPICT() uses GetPicture() to load a PICT resource. If the PICT can’t be found,
beep once, then exit.
/* 9 */
/******************************** LoadPICT *********/
PicHandle LoadPICT( short picID )
{
PicHandle pic;
pic = GetPicture( picID );
if ( pic == NULL )
{
SysBeep( 10 ); /* Couldn't load the PICT resource!!! */
ExitToShell();
}
}
CreateWindow() loads the current PICT, then uses the Rect that defines its
border to define the size of a new window. The idea here is to create a window exactly
big enough to hold the entire PICT. Of course, this wouldn’t be a good idea if the PICT
was bigger than the entire screen. Hmmm... Is this an idea for a column on scroll bars?
We’ll see...
/* 10 */
/******************************** CreateWindow *********/
void CreateWindow( void )
{
WindowPtr window;
PicHandle pic;
Rect r;
pic = LoadPICT( gCurrentPICT );
r = (**pic).picFrame;